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;
}
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;
};
I am just a beginner in C++, my question is can a virtual function access the friend of base class? or the virtual function will only access the class's friend function in which it is defined?
class A
{
friend class B;
public:
virtual void setData();
};
now if a class is derived from class A
class C:public class A{
public:
setData()
{
//can I use the friend class B here?
}
};
First, you have friendship backwards. B is a friend of A, but that gives A zero extra rights over B.
In C++, friendship does not commute. A says B is a friend, but A may not be a friend of B.
Second, friendship is not inherited. You don't go out drinking with your mother's friends.
Third, there are many ways to republish or share rights. The class that is a friend can have a method that does the operation on the friend.
Suppose you really wanted this:
class B {
friend class A;
void doStuff();
};
class A {
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
b->do_stuff();
}
};
C::setData generates an error. But we can change it like this:
class A {
protected:
void do_stuff_on_b(B* b) { b->do_stuff(); }
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
do_stuff_on_b(b);
}
};
we could also generalize this and create an access token:
class B {
struct access_token{ explicit access_token(int) {} };
friend class A;
public:
void doStuff(access_token);
};
class A {
protected:
static B::access_token access_b() { return access_token(0); };
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
b->do_stuff( access_b() );
}
};
where we gatekeep access to B private methods based on possession of an access token that can be passed around. The methods are public, but the token itself can only be created by friends.
Here is a skeleton code:
class C{
callMe(){}
};
class A{
// How to use callMe()
};
class B : C {
callMe();
A a;
};
In this example class B extends class C, so it can call callMe() method. But I need to use callMe() using class A given that class A can not extend class C. I wonder how?
you need to make A contain an object of type C.
class A
{
private:
C objC;
public:
void WhateverMethod() { objC.CallMe(); }
};
Also, the syntax for inheritance is
class B : C{
};
If you want B to simply have access to CallMe(), then you do not need to redefine it in B. It will inherit it from C. If you want B to override CallMe then you need to do this:
class C
{
public:
virtual void CallMe() { //definition }
};
class B : public C
{
public:
void CallMe() { //redefine it here }
};
Note, I assume from your syntax errors that you are a JAVA programmer. Methods are not automatically marked as virtual in C++, you have to mark them as virtual if you want to use polymorphism, and you have to use them from a pointer for it to work.
class C{
callMe(){}
friend class A;
};
class A{
//use call me here
};
You need to provide an instance of C:
class C {
public: // has to be public
void callMe() const {}
};
class A{
public:
A(const C& inst) : inst(inst) {}
void foo() {
inst.callMe();
}
private:
const C& inst;
};
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);