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 {};
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;}
};
The following example is from the book "Inside C++ object model"
class Abstract_base {
public:
virtual ~Abstract_base () = 0;
virtual void interface () const = 0;
virtual const char* mumble () const
{
return _mumble;
}
protected:
char *_mumble;
};
The author says if I want to initialize _mumble, the data member of the pure virtual base class, a "protected constructor" should be implemented.
But why protected? And why "public constructor" is not suitable for this class?
Thanks for your answers, and it would be perfect if there's an example.
It doesn't really matter, since you're not allowed to construct objects of the base class anyway. Making it protected serves only as a reminder of the fact that the class is supposed to be a base class; it's only cosmetics/documentation.
Consider
struct Base {
virtual ~Base() = 0;
protected:
Base() { std::puts("Base constructor"); }
};
Base::~Base() { std::puts("Base destructor"); }
struct Derived : Base {};
int main()
{
//Base b; // compiler error
Derived d;
Base *b = new Derived();
delete b;
}
Removing the protected doesn't change the meaning of the program in any way.
Abstract classes and construction of such
It doesn't matter if the constructor is public or protected, since an abstract class cannot be instantiated.
You must inherit from it in order to have it's constructor called, and since the Derived class calls the constructor of the abstract class it doesn't matter what protection level you choose, as long as the Derived class can access it.
One reason that one could possibly have for making it protected is to serve as a reminder that the class must be constructed through inheritance, but honestly that should be clear enough when seeing that it has pure virtual member-functions.
example snippet
struct B {
virtual void func () = 0;
virtual ~B () = 0 { };
};
B::~B () { }
struct D : B {
void func () override;
};
int main () {
B b; // will error, no matter if Bs ctor is 'public' or 'protected'
// due to pure virtual member-function
D d; // legal, D has overriden `void B::func ()`
}
A pure virtual class cannot be instantiated, so it doesn't make a difference if the constructor is public or protected.
A public constructor is syntactically correct. However, making it protected will carry a stronger indication that the class cannot be instantiated.
For an example: http://ideone.com/L66Prq
#include <iostream>
using namespace std;
class PublicAbstract {
public:
PublicAbstract() { }
virtual void doThings() =0;
};
class ProtectedAbstract {
protected:
ProtectedAbstract() { }
public:
virtual void doMoreThings() =0;
};
class B: public PublicAbstract {
public:
void doThings() { }
};
class C: public ProtectedAbstract {
public:
void doMoreThings() { }
};
int main() {
B b;
C c;
return 0;
}
A public constructor would not be very useful, since abstract classes cannot be instantiated in the first place.
A protected constructor makes sense: this way, a derived concrete class can provide its own public constructor that chains to the protected constructor of the base abstract class.
Protecetd ctor will make sure the ctor gets called by only the classes which derive from Abstract_base.
Public ctor is not suitable because the class contains a pure virtual method! How are you planning to instantiate a pure-virtual class if not via its child classes?
In C++ multiple inheritance with virtual base
i understand why could this code be ambiguous , but why it still complains when i specifically call a derived class method ?
class A {
public:
virtual void f() { cout << 1 ;}
};
class B :virtual public A {
public:
virtual void f() { cout << 2; }
};
class C :virtual public A {
public:
virtual void f() { cout << 3; }
};
class D : public B, public C {};
void main(){
D* d = new D();
d->B::f();
getch();
}
i would expect that it will run the B:f() method but i get :
"ambiguous inheritance of 'void A::f(void)'
The problem is that your function is virtual which means it overrides address in vtable. You can't override one address with two functions.
Without virtual qualifier there would be just ambiguity during the call which can be avoided just like you did specifying base class B::f()
The problem is that your class D has two final overriders of function f. See http://en.cppreference.com/w/cpp/language/virtual about final overrider.
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.
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.