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;}
};
Related
I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}
class A has a pure virtual method read()
class B has an implemented virtual method read()
I have a class C that inherits A and B
Can this happen?
What I'm trying to achieve is that the two base classes A and B complement each other.
So C read() method would actually call class B read()
class A {
virtual int get_data() = 0;
void print() {
log(get_data());
}
}
class B {
virtual int get_data() {
return 4;
}
}
class C : public A, public B {
}
C my_class;
my_class.print(); // should log 4;
I'm not on my computer nor will have opportunity in the next couple of weeks so I can't test this... but I'm designing the architecture and needed to know if this is possible and if not.. how can this be accomplished!
Can multiple base classes have the same virtual method?
Can this happen?
Yes.
So C read() method would actually call class B read()
That doesn't happen automatically. A member function of base doesn't override a function of an unrelated base.
You can add an override to C:
class C : public A, public B {
int get_data() override;
}
This overrides both A::get_data and B::get_data. In order to "actually call class B read()", you can indeed make such call:
int C::get_data() {
return B::get_data();
}
Or... that would be possible if you hadn't declared B::get_data private.
Overriding a function in another base without explicitly delegating in derived is possible if you change your hierarchy a bit. In particular, you need a common base, and virtual inheritance:
struct Base {
virtual int get_data() = 0;
};
struct A : virtual Base {
void print() {
std::cout << get_data();
}
};
struct B : virtual Base {
int get_data() override {
return 4;
}
};
struct C : A, B {};
I am trying to learn inheritance in c++. I wrote some code to learn virtual functions.
#include <iostream>
using namespace std;
class A {
int a;
public:
A() {}
virtual int get_count() const = 0;
int get_A() { return a; }
};
class B : public A{
public:
int b;
B() {}
B(A& base)
: b(base.get_count()) {}
virtual int get_count() const { return 10; }
};
void func(A& base) {
B derived(base);
cout << derived.b;
}
int main() {
A base;
B derived;
func(derived);
}
When I try to compile I get this error:
test_inheritance_vir.cpp: In function ‘int main()’:
test_inheritance_vir.cpp:32: error: cannot declare variable ‘base’ to be of abstract type ‘A’
test_inheritance_vir.cpp:5: note: because the following virtual functions are pure within ‘A’:
test_inheritance_vir.cpp:10: note: virtual int A::get_count() const
Can you please tell me what I am doing wrong?
You are trying to instantiate an object of type A with A base;. It's not possible as A contains a pure virtual function. (get_count()) Suppose I tried calling base.get_count().
The method virtual int get_count() const = 0; is pure virtual. You can't create an object of a class that is abstract (or in other words - has a pure virtual member). If you want to create an object of A, remove the = 0 and define the function (with an empty body if you need):
virtual int get_count() const{};
should work.
The way you have implemented A (below) causes it to be an abstract base class.
class A
{
int a;
public:
A() {}
virtual int get_count() const = 0; // this is a pure virtual function
int get_A() { return a; }
};
It can only be used as a pointer to a derived class that implements the pure virtual functions:
int main()
{
B derived;
A* pA = new B; // this is okay
delete pA;
return 0;
}
The answers above are the technical reasons why it won't work, but there's a more insidious problem in that the design doesn't make sense. You're creating a B to add some functionality to your A. If you also create a C that extends A, do you really want to turn that into a B?
The classic example of inheritance is animals. Zebra and Giraffe are both Animals, so a class hierarchy would look like this
class Animal
{
stuff
}
class Zebra : public Animal
{
more stuff
}
class Giraffe : public Animal
{
different stuff
}
It doesn't make much sense to turn a Zebra into a Giraffe, though, even though both are animals.
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);
I have not programmed in c++ in a long time and want some simple behavior that no amount of virtual keywords has yet to produce:
class Base {
public:
int both() { return a(); }
};
class Derived : public Base {
protected:
int a();
};
class Problem : public Derived {
};
Problem* p = new Problem();
p.both();
Which gives me a compile-time error. Is this sort of behavior possible with c++? Do I just need forward declaration? Virtual keywords on everything?
No. You will have to use a pure virtual a in base.
class Base {
virtual int a() = 0;
int both() {
return a();
}
};
You should declare the a() function as a pure virtual method in the Base class.
class Base {
int both() {
return a();
}
virtual int a()=0;
};
Then implement the a() method in the Derived class
class Derived : public Base {
int a(){/*some code here*/}
};
And finally, Problem class doesn't see the both() method, since its private in Base. Make it public.
class Base {
public:
int both() {
return a();
}
};
Your function both() is private by default. Try:
class Base {
public:
int both() {
// ...
(In the future, it would be helpful if you tell us what the actual error message was.)
You need a() to be declared in class Base, otherwise the compiler doesn't know what to do with it.
Also, both() is currently a private method (that's the default for classes), and should be made public in order to call it from main.
You have multiple problems in your code :
unless you declare them public or protected, elements of a class are private as a default.
you need a virtual keyword to define a virtual function that would be callable in a parent.
new returns a pointer to Problem.
Here's a complete working code based on your test :
class Base {
protected:
virtual int a()=0;
public:
int both() {
return a();
}
};
class Derived : public Base {
private :
int a()
{
printf("passing through a!");
return 0;
}
};
class Problem : public Derived {
};
int main(void)
{
Problem* p = new Problem();
p->both();
}
tested on CodePad.
As others point out, you need to declare a() as pure virtual method of Base and change access to public to make your snippet work.
Here is another approach possible in c++: instead of virtual functions, you can use static polymorphism via the Curiously recurring template pattern:
template <class D>
class Base : public D
{
public:
int both() { return D::a(); }
};
class Derived : public Base<Derived>
{
public:
int a();
};
I'm posting this approach since you're asking what is possible in c++. In practice, virtual methods are most often a better choice because of their flexibility.