Context: I'm doing some internal cleanup to move away from large & unwieldy data structures to more well-defined data structures.
Current
I have a class that does something like this:
class Base {
public:
virtual int DoStuff(BigType input);
};
Calling code:
std::vector<Base*> bases;
BigType input;
for (const auto& base : bases) {
base.DoStuff(input);
}
Child classes currently look like this:
class Child : public Base {
int DoStuff(BigType input) const override {
// do stuff
}
};
Attempted
I added an intermediate interface:
template <typename SmallType>
class FocusedBase : public Base {
public:
int DoStuff(BigType input) const override {
return DoStuff(SmallType(input));
}
virtual int DoStuff(SmallType input);
};
Child classes now look like this. Note that SmallType may differ across child classes:
class Child : public FocusedBase<SmallType> {
int DoStuff(SmallType input) {
// do stuff
}
};
Calling code remains the same.
Issue
I'd like to have new classes inherit from FocusedBase only, not Base. Any thoughts on how to do so?
If you want to disallow inheriting from Base directly you can make Base::Base() private and make FocusedBase a friend:
struct Base {
private:
Base() = default;
friend class FocusedBase;
};
struct FocusedBase : Base {};
struct Foo : Base {};
struct Bar : FocusedBase {};
int main() {
//Foo f; // error
Bar b; // ok
}
Related
My goal is to have a base client use a base class as an input. I would like to be able to extend the implementation of the base client through a derived client that takes a derived class as an input.
struct Base
{
int a, b, c;
...
};
struct Derived: public Base
{
int d, e;
...
};
class BaseClient
{
public:
BaseClient(const Base& b) : b(b)
{}
void processA(){...}
void processB(){...}
...
private:
Base b;
};
class DerivedClient : public BaseClient
{
public:
DerivedClient(const Derived& d) : BaseClient(d), d(d)
{}
void processD(){...}
void processE(){...}
...
private:
Derived d;
};
The bulk of the implementation is done in the BaseClient so taking advantage of that is a must. The problem I am having is that the Base class can get accessed in two different ways in the DerivedClient class. Once through the BaseClient and another through the Derived class data member. What is the best design practice in this situation?
Inheritance is likely not the best way to model client here, for Base / Derived is a parameter (type argument), not a different type. However, if you really want to solve it using inheritance, it can be solved via CRTP:
template<typename D>
class BaseClientImpl
{
public:
Base& getB() { return static_cast<D*>(this)->data; }
void processA(){ /*...*/ }
void processB(){ /*...*/ }
// ...
// no private b here
};
template<typename D>
class DerivedClientImpl : public BaseClientImpl<D>
{
public:
Base& getD() { return static_cast<D*>(this)->data; }
void processD(){ /*...*/ }
void processE(){ /*...*/ }
// ...
// no private d here
};
struct BaseData
{
Base data;
};
struct DerivedData
{
DerivedData;
};
using BaseClient = BaseClientImpl<BaseData>;
using DerivedClient = DerivedClientImpl<DerivedData>;
However, if you're willing to give up on the requirement that DerivedClient inherits from BaseClient and would only like to reuse the data, then it's perhaps simpler to make it via templates and SFINAE. In this case, you only have one template client:
template<typename Data>
class Client
{
public:
Client(const Data& d) : d(d) {}
// functions that always exist:
void processA(){ /*...*/ }
void processB(){ /*...*/ }
// ...
// functions that require data to be Derived
std::enable_if_t<std::is_base_of_v<Derived, Data>>
processD() { /*...*/ }
std::enable_if_t<std::is_base_of_v<Derived, Data>>
processE() { /*...*/ }
// ...
private:
Data d;
};
Let a class hierarchy :
class Base { virtual ~Base() throw(); };
class DerivedA : public Base { };
class DerivedB : public Base { };
I would like to have some code specific to each of these derived classes. However that code also being specific to the application that makes use of this class hierarchy, I do not want to embbed this derived-class-specific code into these derived classes. To avoid doing so, I thought about writing free functions :
void DerivedASpecificWork( DerivedA da );
void DerivedBSpecificWork( DerivedB db );
However, when given an instance of a derived class through a reference/pointer to a Base, I do not have access to the actual type of the instance, and thus cannot call the proper Derived*SpecificWork() function.
I would like to know if there is nome kind of design pattern that would allow me to call a derived-class-specific function without knowing the actual type of the instance, i.e having the same mechanism as virtual functions provide, but without having these virtual functions that would require me to embbed application-specific code into that class hierarchy.
Actually, why I want to do that is to provide informations about an exception that occured within a natively implemented function called by a Lua script. Each exception carrying its own set of information, the way I want to represent the error within the script depends on the type of the exception. I could create a pure virtual method in the base class that would be implemented by derived classes, but this would require me to embbed Lua-related code into my exception hierarchy, which I do not want to do since the Lua is specific to one of the application using that exception hierarchy.
Also I cannot use C++11.
Thank you.
May be Brigde pattern can help you.
This pattern can be used when you want to avoid a permanent binding between an abstraction and it's implementation.
(I don't see your comment about your restriction in using c++11, but you can remove std::unique_ptr, std::move and override keyword)
class AppSpecificImp
{
public:
virtual void DoWork() = 0;
};
class Base
{
public:
virtual ~Base() throw();
virtual DoWork() = 0;
};
class DerivedA : public Base
{
public:
DerivedA(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedA specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
class DerivedB : public Base
{
public:
DerivedB(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedB specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
Edit to show Visitor pattern usage:
With visitor pattern you can do what you want but with more Effort.
class Visitor
{
public:
virtual void VisitDerivedA(DerivedA* object) = 0;
virtual void VisitDerivedB(DerivedB* object) = 0;
};
class Base
{
public:
virtual void Visit(Visitor* visitor) = 0;
};
class DerivedA : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedA(this);
}
};
class DerivedB : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedB(this);
}
};
class AppSpecificVisitor : public Visitor
{
public:
void VisitDerivedA(DerivedA* object)
{
// Do any work related to DerivedA class
}
void VisitDerivedB(DerivedB* object)
{
// Do any work related to DerivedB class
}
}
int main()
{
AppSpecificVisitor myVisitor;
Base* myBase = // any class in your hierarchy
myBase->Visit(&myVisitor);
}
As I said in comments with Visitor pattern you can add new functionally without changing the main hierarchy(Base->Derived types). You just define a new visitor implementation and write your logic for every class in main hierarchy. In your example you can pack app specific logic in an object and reference that in your derived objects that is an easier approach.
Why not using a new set of hierarchy for application specific implementation ?
class AppBase
{
public:
virtual ~AppBase() throw();
virtual void work_with_app() = 0;
};
class Base
{
public:
Base(AppBase& app) : m_app(app) {}
virtual ~Base() throw();
protected:
AppBase& m_app;
};
class DerivedA : public Base { DerivedA(AppBase& app) : Base(app) {} };
class DerivedB : public Base { DerivedA(AppBase& app) : Base(app) {} };
// Application specific implementation :
class AppLuaSpecific : public AppBase
{
public:
void work_with_app() { /* Lua app specific */ }
};
This way, your 1st hierarchy : Base, DerivedA, DerivedB can live without knowing anything about the app specific code implemented in AppLuaSpecific.
You can implement your own app-specific dispatch as follows (check it live on Coliru):
#include <iostream>
#include <typeinfo>
struct Base { virtual ~Base() {} };
struct DerivedA : public Base { };
struct DerivedB : public Base { };
namespace AppSpecific
{
template<class F>
void dispatch(const Base& b)
{
const std::type_info& t = typeid(b);
if ( t == typeid(DerivedA) )
F::doit(static_cast<const DerivedA&>(b));
else if ( t == typeid(DerivedB) )
F::doit(static_cast<const DerivedB&>(b));
}
struct Foo
{
static void doit(const DerivedA& da) { std::cout << "Foo(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Foo(DerivedB)\n"; }
};
struct Bar
{
static void doit(const DerivedA& da) { std::cout << "Bar(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Bar(DerivedB)\n"; }
};
} // namespace AppSpecific
int main()
{
DerivedA da;
DerivedB db;
Base& b1 = da;
Base& b2 = db;
AppSpecific::dispatch<AppSpecific::Foo>(b1);
AppSpecific::dispatch<AppSpecific::Foo>(b2);
AppSpecific::dispatch<AppSpecific::Bar>(b1);
AppSpecific::dispatch<AppSpecific::Bar>(b2);
}
Is it possible to have a different type definition based on which derived class is instantiated?
Say I have a parent class with a virtual function func(), two int members and a vector of type myType, and two child classes, which share the same int members, and the vector, but their implementation of func() require myType to be slightly different.
For example:
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<myType> vec;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
Can I do something like this? when I have tried it, it creates a circular dependency in the header files, because class Parent is required to be included first, but then it requires myType to be defined.
Is there a way of forward declaring myType depending on class? or do I just need to include a different vector of myType in each class like so:
class Parent {
protected:
int myMember;
int myOtherMember;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
std::vector<myType> vec;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
std::vector<myType> vec;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
This is a job for templateman!
First we declare Parent
template <class TYPE>
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<TYPE> vec;
public:
Parent(TYPE variable);
virtual int func() = 0;
};
Unfortunately a custom type contained within Child1 is out with this approach because the type needs to be declared before we can specialize a template on it. I'm using int and double here for ease. Replace as needed.
using Child1Type = int;
// or typedef int Child1Type; pre-C++11
class Child1 : public Parent<Child1Type> {
public:
Child1(Child1Type variable) : Parent(variable){};
int func() {return someFunc();};
};
using Child2Type = double;
class Child2 : public Parent<Child2Type> {
public:
Child2(Child2Type variable) : Parent(variable){};
int func() {return someOtherFunc();};
};
EDIT
Kicking myself for not getting this earlier (and burning way too much time because I knew it had to be possible, but was thinking in the wrong direction)
Declare the type up in Parent. Set the access based on who need to be able to see the type. Here I made Type public to test it out in main. The Type is declared in Parent and is visible to (and through because it's public) the Children.
Also stripped out everything that wasn't immediately necessary and used fixed width integer types so I could easily demonstrate the differences.
I think this is exactly what Pixelchemist was alluding to.
template <class TYPE>
class Parent {
public:
using Type = TYPE; // declare Type here
protected:
int myMember;
int myOtherMember;
std::vector<Type> vec; // visible here
public:
Parent(Type variable); // here
virtual ~Parent(){}
virtual int func() = 0;
};
class Child1 : public Parent<uint16_t> { // complicated type needs to be reproduced
// only once, here in the specialization
public:
Child1(Type variable) : Parent(variable){};
};
class Child2 : public Parent<uint32_t> {
public:
Child2(Type variable) : Parent(variable){};
};
int main()
{
// and visible way down here in main through Child1 and Child2
std::cout << "Child 1: " << sizeof(Child1::Type) << std::endl;
std::cout << "Child 2: " << sizeof(Child2::Type) << std::endl;
}
output is
Child 1: 2
Child 2: 4
You could simply use templates:
template<class T>
struct Base
{
std::vector<T> v;
};
struct D1 : public Base<int>
{
// all stuff in here comes into play when deriving from Base is already done
// Thus, compiler cannot know any typedefs from here inside Base...
};
struct D2 : public Base<double>
{
};
where you cannot use a typedef from derived in base class. See CRTP refer to typedef in derived class from base class.
This is what templates are for:
<template typename T>
class Child : public Parent {
private:
std::vector<T> vec;
public:
Child(variable) : Parent(variable) {};
int func() { return someOtherFunc(); };
}
Then Child is declared as something like:
Child<int> myChildInstance(10);
In C++11, I can expose an enumerator which is protected in a base class, to users of a derived class, as follows:
class Base
{
protected:
enum Waldo { hidden, found };
};
class Derived : public Base
{
public:
using Base::Waldo;
}
void foo()
{
Derived::Waldo w = Derived::Waldo::found;
}
Unfortunately, in C++03, Derived::Waldo::found is illegal, and Derived::found is met with 'Base::Waldo Base::found' is protected within this context.
I could work around that by also writing a using for each enumerator:
class Derived : public Base
{
public:
using Base::Waldo;
using Base::hidden;
using Base::found;
}
void foo()
{
Derived::Waldo w = Derived::found; // works in C++03
}
but this can be really tedious to do if the enumerator has many enumerators. Is there a way to pull off this enum-exposing in C++03 without this tedium?
SCNR!
struct Wrap
{
enum Waldo { hidden, found };
};
class Base : protected Wrap
{
};
class Derived : public Base
{
public:
using Base::Wrap;
};
void foo()
{
Derived::Wrap::Waldo w = Derived::Wrap::found;
}
Edit: Or you put it inside:
class Base
{
protected:
struct Wrap
{
enum Waldo { hidden, found };
};
};
class Derived : public Base
{
public:
using Base::Wrap;
};
void foo()
{
Derived::Wrap::Waldo w = Derived::Wrap::found;
}
Well, I think there are lots of different ways to do this, depending on what you want to do with the enum. Here is one:
struct WaldoStates
{
enum States{hidden, found};
};
class Base
{
public:
typedef WaldoStates Waldo;
};
class Derived : public Base
{
};
void foo()
{
WaldoStates::States state = Derived::Waldo::found;
}
Now, this is good if simply want the states to be accessible with something like myClass::Waldo::hidden in any class of the inheritance tree. If you want to be able to set different states for some of the derived classes, you may want to do something like this instead:
struct WaldoStates
{
typedef int State;
};
struct DefaultWaldoStates : public WaldoStates
{
enum States{hidden, found};
};
struct OtherWaldoStates : public WaldoStates
{
enum States{stillHidden, alreadyFound};
};
class Base
{
public:
typedef DefaultWaldoStates Waldo;
};
class Derived : public Base
{
};
class OtherDerived : public Base
{
public:
typedef OtherWaldoStates Waldo;
};
void foo()
{
WaldoStates::State state0 = Derived::Waldo::found;
WaldoStates::State state1 = OtherDerived::Waldo::alreadyFound;
}
I'm looking for a clean way of doing this since a long time. In my problem, there exist 3 classes not sharing any parent in common but each having some methods with the same name (A.doSomething, B.doSomething, C.doSomething). Hence, having the same function signature, class D inheriting from A and using method doSomething() will "look the same" to E inheriting from B or C .
Here is a sketch of what I'd like to be able to do:
class Base {
public:
void myMethod(void) { doSomething(); }
};
class Independent {
public:
doSomething();
};
clase Derived : public Base : public Independent {
(...)
};
int main(void) {
Derived *derivedObject = new Derived();
derivedObject->myMethod();
}
In this problem, object of type "Independent" is provided by a library that I cannot change. I would like to define a base class that uses methods that are going to be inherited later on. I couldn't find a proper way of doing this using virtual inheritance without causing ambiguous compiling.
You've got a nasty situation there. One solution to this would be using the Curiously Recurring Template Pattern to perform the inheritance at compile-time, like this:
template <typename D>
class Base {
public:
void myMethod(void) { static_cast<D*>(this)->doSomething(); }
};
class Independent {
public:
void doSomething();
};
clase Derived : public Base : public Independent {
/*...*/
};
int main(void) {
Derived *derivedObject = new Derived();
derivedObject->myMethod();
}
Alternatively, you could choose to put a middleman class in between to forward to Independent (I assume you have many classes deriving from the same Base and Independent, and just don't want to have to do this for each class).
template <typename D>
class Base {
private:
virtual void doSomethingImpl();
public:
void myMethod(void) { doSomethingImpl(); }
};
class Independent {
public:
void doSomething();
};
class IndependentWrapper : public Base : public Independent {
private:
void doSomethingImpl() { Independent::doSomething(); }
};
clase Derived : public IndependentWrapper {
/*...*/
};
int main(void) {
Derived *derivedObject = new Derived();
derivedObject->myMethod();
}