I have internal objects, which should'nt be used by client code :
class InternalA {};
class InternalB {};
I have public interface objects A, B, C. Internally, i need to construct objetcs InternalA from A and InternalB from B, but A and B can only be accessed by a pointer to base class C. I could use covariant virtual method but doing so, my Internals become public, and InternalA and InternalB are not really two subtytes of the same base class.
Or i could do something like that :
class C {
// some data
public:
C() {};
// some pure virtual methods and virtual methods
virtual C *getConcrete(void) const =0;
};
class B : C {
public:
//methods
virtual B *getConcrete(void) { return static_cast<B>(this); };
};
class A : C {
public:
//methods
virtual A *getConcrete(void) { return static_cast<A>(this); };
};
And then use an internal builder with polymorphic method in A or B parameter.
Edit :
To build InternalA and InternalB, i can use a function/method like that :
void somefunction(A *a) {
InternalA x(<using a->smthg>);
// do stuffs
};
void somefunction(B *b) {
InternalB x(using b->smthg>);
//do stuffs
};
What do you think about this hack ?
I think its impossible to solve this problem using only class C. To build InternalA or InternalB you need knowledge about A or B. At builder definition A or B must be defined. So I think you should use dynamic_cast. Or some kind of type id implemented by virtual functions if dynamic_cast is prohibited.
#include "A.h"
......
InternalA* buildInternalA(const C* c) {
const A* a = dynamic_cast<const A*>(c);
if (a)
return new InternalA(a);
return 0;
}
But where you use builder(in other cpp file), you don`t need definition of A and B, only declaration of builder:
class InternalA;
class C;
InternalA* buildInternalA(const C* c);
Related
I have a base class B derived from an abstract class A. The idea of having abstract class A is to facilitate Dependency Injection and Mocking while unit testing. So A have no implementation. Almost like C# interface. All works fine.
Now I have a derived class D that is inherited from B. The problem now is D does not have an abstract class to facilitate DI or Mocking. Here is a little code that explains the problem:
class A // Abstract
{
public:
virtual String Identify() = 0;
};
class B : public A
{
public:
String Identify() {return "B"; }
};
class D : public B
{
public:
String D_Work() {return "D_Work"; }
};
So to use B, I do A *b = new B(); which is fine. The using class does not know the type B. new() is done by a factory or the object is just passed in.
But to use D, I either need the actual type (which I am trying to get away) or use type A and cast to call methods like A *d = new D(); ((D*)d)->D_Work()) (using c-style for simplicity) which again will require the user to know the type. Any thoughts on the design?
You can add another abstract class in between B and D:
class B : public A {
public:
string Identify() {return "B"; }
};
class C : public B {
public:
virtual string D_Work() = 0;
};
class D : public C {
public:
string D_Work() {return "D_Work"; }
};
See it work here: ideone
It looks like I may have misunderstood what you want. It seems you want to be able to continue using only an A pointer. In that case, I'd add a virtual D_Work() function to A that throws:
class A {
public:
virtual string Identify() = 0;
virtual string D_Work() { throw; } // If it's not defined, throw
};
See it work here: ideone
The other approach is that you have multiple interfaces I, J ,K, and pure methods in A like GetI() that return pointers to that interface.
Then All your implementation classes implement A, plus any other interfaces plus any of the GetX() methods.
Your interface is A,I,J,K, and that is all that is exposed. That is all that needs to be mocked.
Ultimately, the continuous updating of A to add new classes gets tiresome, so you invest in a different mechanism for getting the interfaces, probably based on a token declared in the interface class, and a template method in A that resolves the token and return type by calling an implementation method that does the same. Or you just give up and let the caller dynamic_cast to the interfaces.
Sometime soon you end up with COM, or something very like it.
class A;
{
virtual String Identify() = 0;
virtual I* GetI() { return nullptr;}
virtual J* GetJ() { return nullptr;}
virtual K* GetK() { return nullptr;}
};
class I
{
virtual void Work() =0;
};
class J
{
virtual void MoreWork() =0;
};
class B: A, I
{
void Work() {}
I* GetI() { return this;}
};
class C: A, J
{
void MoreWork() {}
I* GetJ() { return this;}
};
Suppose there are two unchangeable classes from a library, A and B, related like here:
class A
{
public:
virtual void doCustomThings() = 0;
virtual void doOtherThings() = 0;
void doSomething();
private:
SomeType1 someData;
};
class B : public A
{
public:
void doCustomThings() override;
void doOtherThings() override;
void someUsefulUtility();
private:
SomeType2 otherData;
};
I'm trying to implement the interface of A in terms of the some available in B, so I do:
class C : public B
{
public:
void doCustomThings() override; // uses B::someUsefulUtility()
// leave B::doOtherThings() not overridden
private:
SomeType3 myData;
};
But I don't intend C to be B, i.e. I don't want references to C to be implicitly convertible to B&, although it should be convertible to A&.
First thing coming to mind is to use virtual inheritance, and then inherit public A, private B. But the A and B classes in my case are not editable, and for virtual inheritance to work here I need class B to inherit as public virtual A.
Another idea is to consider composition instead of inheritance. But if I derive from A and have B as a private member, I'll uselessly have A::someData twice, which looks inelegant.
Is there any good way to so something like class C : public A, private B, so that there'd be only one base class A, given the above mentioned constraints?
Yes, use private inheritance and exposed the desired members with using.
class C : private B
{
public:
using B::A;// to make it convertible to A
using B::doOtherThings;
void doCustomThings() override {
std::cout<<"C::doCustomThings()\n";
}
private:
char myData;
};
Working example.
Yes, only use inheritance for A, use composition for B, and delegate to the B member (not base)
class C : public A
{
public:
void doOtherThings() override { myB.doOtherThings(); }
void doCustomThings() override {
std::cout<<"C::doCustomThings()\n";
}
private:
B myB;
SomeType3 myData;
};
So, I have an abstract class A, which I implement in B.
B uses C, and A cannot depend on C. so how do I set it?
I dont want to use a dynamic cast and add a setter to B.
class A
{
public:
virtual void doSomething() const = 0;
}
class C
{}
class B
{
public:
virtual void doSomething() const { mVar; }
private:
C mVar;
}
I am trying to figure out an interesting multiple inheritance issue.
The grandparent is an interface class with multiple methods:
class A
{
public:
virtual int foo() = 0;
virtual int bar() = 0;
};
Then there are abstract classes that are partially completing this interface.
class B : public A
{
public:
int foo() { return 0;}
};
class C : public A
{
public:
int bar() { return 1;}
};
The class I want to use inherits from both of the parents and specifies what method should come from where via using directives:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
};
When I try to instantiate a D I get errors for trying to instantiate an abstract class.
int main()
{
D d; //<-- Error cannot instantiate abstract class.
int test = d.foo();
int test2 = d.bar();
return 0;
}
Can someone help me understand the problem and how to best make use of partial implementations?
You don't have diamond inheritance. The B and C base classes of D each have their own A base class subobject because they do not inherit virtually from A.
So, in D, there are really four pure virtual member functions that need to be implemented: the A::foo and A::bar from B and the A::foo and A::bar from C.
You probably want to use virtual inheritance. The class declarations and base class lists would look like so:
class A
class B : public virtual A
class C : public virtual A
class D : public B, public C
If you don't want to use virtual inheritance then you need to override the other two pure virtual functions in D:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
int B::bar() { return 0; }
int C::foo() { return 0; }
};
You need to make your base classes virtual in order for them to inherit properly. The general rule is that all non-private member functions and base classes should be virtual UNLESS you know what you're doing and want to disable normal inheritance for that member/base.
I have a quite complex class hierarchy in which the classes are cross-like depending on each other: There are two abstract classes A and C containing a method that returns an instance of C and A, respectively. In their inherited classes I want to use a co-variant type, which is in this case a problem since I don't know a way to forward-declare the inheritance relation ship.
I obtain a "test.cpp:22: error: invalid covariant return type for ‘virtual D* B::outC()’"-error since the compiler does not know that D is a subclass of C.
class C;
class A {
public:
virtual C* outC() = 0;
};
class C {
public:
virtual A* outA() = 0;
};
class D;
class B : public A {
public:
D* outC();
};
class D : public C {
public:
B* outA();
};
D* B::outC() {
return new D();
}
B* D::outA() {
return new B();
}
If I change the return type of B::outC() to C* the example compiles. Is there any way to keep B* and D* as return types in the inherited classes (it would be intuitive to me that there is a way)?
I know of no way of having directly coupled covariant members in C++. You'll have either to add a layer, or implement covariant return yourself.
For the first option
class C;
class A {
public:
virtual C* outC() = 0;
};
class C {
public:
virtual A* outA() = 0;
};
class BI : public A {
public:
};
class D : public C {
public:
BI* outA();
};
class B: public BI {
public:
D* outC();
};
D* B::outC() {
return new D();
}
BI* D::outA() {
return new B();
}
and for the second
class C;
class A {
public:
C* outC() { return do_outC(); }
virtual C* do_outC() = 0;
};
class C {
public:
virtual A* outA() = 0;
};
class D;
class B : public A {
public:
D* outC();
virtual C* do_outC();
};
class D : public C {
public:
B* outA();
};
D* B::outC() {
return static_cast<D*>(do_outC());
}
C* B::do_outC() {
return new D();
}
B* D::outA() {
return new B();
}
Note that this second option is what is done implicitly by the compiler (with some static checks that the static_cast is valid).
As far as I know, there's no way to do this without explicit casting. The problem is that the definition of class B can't know that D is a subclass of C until it sees a full definition of class D, but the definition of class D can't know that B is a subclass of A until it sees a full definition of class B, and so you have a circular dependency. This can't be resolved with forward-declarations because a forward declaration unfortunately cannot specify an inheritance relationship.
There's a similar problem with trying to implement a covariant clone() method using templates, which I found can be solved, but the analogous solution still fails here because the circular reference remains impossible to resolve.
You can't do this due to client side expectation. When using a C instance, you can't tell which kind of C it is (a D or something else). Thus, if you store the B pointer (resulting from a call to the derived class but you don't know it at compile time) into a A pointer, I'm not sure that all the memory stuff will be right.
When you call a method on a polymorphic type, the runtime environment has to check the dynamic type of the object and it moves pointers to suit to your class hierarchy. I'm not sure that you should rely on covariance. Have a look at this