Here is the code which causes a problem:
class Base
{
public:
virtual void fun()
{
cout<<"Base";
}
};
class Der:public Base
{
Base &pb;
public:
Der(Base&b):pb(b){}
virtual void fun()
{
cout<<"Der...";
pb.fun();
}
};
int main()
{
Der(Der(Base())).fun();
return 0;
}
Run this code,and the result shows "Der...Base..."! This is so amazing, I can't figure it out why the result is not "Der...Der...Base" which is logically right?!
Then I replace the member in class Der Base&pb with Base*pb and change the code into legal, finnaly the output is right which is "Der...Der...Base"!
I debug the code and find that when I use Base&pb, the constructor of Der only ran once while use Base*pb, the constructor ran twice correctly!
Any one who can explain to me what had happened and why?
In Der(Der(Base())).fun() expression the inner Der(Base()) yields an rvalue - the compiler optimizes the code by using copy elision and removes unnecessary copying of objects.
In addition to the #icepack's answer and the following discussion in the comments (summary: the code Der(der) is a cast, which may or may not be realized using constructor; in your case it's not), a workaround for you: you should make your intention clear by not using the constructor.
I would rewrite your code into something like this:
class Base
{
public:
virtual void fun()
{
cout<<"Base";
}
};
class Der:public Base
{
Base &pb;
Der(Base& b) : pb(b) {}
public:
static Der Decorate(Base&& b){ return Der(b); }
virtual void fun()
{
cout<<"Der...";
pb.fun();
}
};
int main()
{
Der::Decorate(Der::Decorate(Base())).fun();
return 0;
}
(outputs: Der...Der...Base).
Changing the code to accept the pointer is easy:
class Base
{
public:
virtual void fun()
{
cout << "Base";
}
};
class Der : public Base
{
Base* pb;
Der(Base* b) : pb(b) {}
public:
static Der Decorate(Base* b){ return Der(b); }
virtual void fun()
{
cout << "Der...";
pb->fun();
}
};
int main()
{
Der::Decorate(&Der::Decorate(&Base())).fun();
return 0;
}
Related
I'm working on a small project, and I found myself in a situation like this :
class A{}
class B : class A {
public:
void f();
int getType() const;
private:
int type;
}
class C : class A{
public:
int getType() const;
private:
int type;
}
I want to know if there's a way to call the f() function (in class B) from an object of type A?
I tried this but it says function f() cannot be found in class A :
int main(){
vector<A*> v;
// v initialized with values of A ...
if (v->getType() == 1){ // 1 is the type of B
v->f();
}
}
As you've seen, this code won't compile because A doesn't have an f method. In order to make it work, you'd have to explicitly downcast the pointer:
B* tmp = dynamic_cast<B*>(v);
tmp->f();
To begin with, with your current classes, you can't call getType() on an A*. Because the interface of A doesn't have this method. To solve this problem, you either need to make getType a virtual function in A, or move the type field to base class A (as protected) and initialize it in the constructors of the child classes. Let me show you the first method, because I think it is a better approach, since it makes the objective of this function more clear.
class A {
public:
virtual int getType() { return 0; } // or delete the function: ... getType() = 0;
}
class B : public A {
public:
int getType() override { return 1; }
}
With these classes, once you create an instance of B, getType() returns 1 when called on that instance, whether it is pointed to by an A* or B*:
A *object = new B();
object->getType(); // returns 1
Now, if you need to access the f() from B, you can again add it as a virtual method to A's interface, or make a cast to B*.
Using a virtual method:
class A {
public:
virtual void f() { /* a default action maybe? */ }
}
class B : public A {
public:
void f() /* override if you want */ { /* whatever this function does in B */ }
}
...
for (A *ptr : v)
ptr->f();
Using a cast:
class A {
public:
virtual int getType() { return 0; }
}
class B : public A {
public:
void f();
int getType() override { return 1; }
}
...
for (A *ptr : v)
if (ptr->getType() == 1)
dynamic_cast<B*>(ptr)->f();
I understand how C++ solves the diamond problem in multiple inheritance by using virtual inheritance. Suppose the following situation:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C : public A {
void fooc() { int x = get_num(); }
};
class D : public B, public C {
void food() { int x = get_num(); }
};
The get_num() call is ambiguous inside food(). I know I can fix it either by calling A::get_num() or by virtual inheritance using virtual public A. But I can see a third approach:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C { // won't inherit from A anymore
const A& base; // instead keeps a reference to A
void fooc() { int x = base.get_num(); }
public:
explicit C(const A* b) : base(*b) { } // receive reference to A
};
class D : public B, public C {
void food() { int x = get_num(); }
public:
D() : C(this) { } // pass "this" pointer
};
The external code doesn't need to consider C as an A.
Considering it has no impacts on my particular class hierarchy design, are there any advantages of the third approach over the virtual inheritance way? Or, in terms of cost, it ends up being the same thing?
Congratulations ! You've just re-invented the principle of composition over inheritance !
If this works with your design, it means that C was in fact not a kind of A, and there was no real justification to use inheritance in first place.
But don't forget the rule of 5 ! While your approach should work in principle, you have a nasty bug here : with your current code, if you copy a D object, its clone uses the wrong reference to the base (it doesn't refer to it's own base, which can lead to very nasty bugs...
Demo of the hidden problem
Let's make A::get_num() a little bit more wordy, so that it tells us about the address of the object that invokes it:
int get_num() const {
cout << "get_num for " << (void*)this <<endl;
return num;
}
Let's add a member function to C, for the purpose of the demo:
void show_oops() { fooc(); }
And same for D:
void show() { food(); }
Now we can experiment the problem by running this small snippet:
int main() {
D d;
cout<<"d is "<<(void*)&d<<endl;
d.show();
d.show_oops();
D d2=d;
cout<<"d2 is "<<(void*)&d2<<endl;
d2.show();
d2.show_oops();
}
Here an online demo. You will notice that d2 does produce inconsistent results, like here:
d is 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
d2 is 0x7fffe0fd11b0
get_num for 0x7fffe0fd11b0
get_num for 0x7fffe0fd11a0 <<< OUCH !! refers to the A element in d !!
Not only do you refer to the wrong object, but if the d object would decease, you would have a dangling reference, so UB.
I need a class hierarchy in which the derived classes will have implementation of a virtual function that differs in the return type. How can i do it. What i have tried is the following code:
using namespace std;
class Base
{
public:
Base()
{
cout<<"Constructor of Base"<<endl;
}
virtual Base& Decode()=0;
virtual operator int(){return -1;}
virtual operator string(){return "WRONG";}
};
class Der1:public Base
{
int i;
public:
Der1(int j=0):Base(),i(j)
{
cout<<"COnstructor of Der1"<<endl;
}
Base& Decode()
{
cout<<"Decode in Der1"<<endl;
return *this;
}
operator int()
{
return i;
}
};
class Der2:public Base
{
string s;
public:
Der2(string temp="sajas"):Base(),s(temp)
{
cout<<"Constructor of Der2"<<endl;
}
Base& Decode()
{
cout<<"Decode in Der2"<<endl;
return *this;
}
operator string()
{
return s;
}
};
int main()
{
Base *p=new Der1();
int val=p->Decode();
}
I was thinking if it could work this way user would just have to equate the object to a valid variable. Is there any way to do it without including all the conversion operators in Base with some dummy implementatin?
I guess there is one problem, if it is a Pure virtual function you cannot create an object of the class base. But on the other hand to solve your problem you can try out using templates, something like below.
#include <iostream>
class Base{
public:
Base(){}
virtual ~Base(){}
virtual void show() const {
std::cout << "Base::show()!" << std::endl;
}
};
class A:public Base{
public:
A(){}
virtual ~A(){}
virtual void show() const{
std::cout << "A::show()!" << std::endl;
}
};
template<typename T>
class Factory{
public:
const T* operator()() const{
return &t;
}
private:
T t;
};
int main(){
const A* pA = Factory<A>()();
pA->show();
Factory<A>()()->show();
return 0;
}
What is a better way to implement this in C++ (without if-else). In C I can initialize function pointer, and then just call function pointers. So if you look at class C, some objects of class C use only class A and some class B. I am more familiar with C than C++.
class A {
public:
int func1();
int func2();
int func3();
};
class B:A {
public:
int func1() {x=1; A::func1();}
int func2() {A::func2(); x=1;}
int func3() {x=1; A::func2();}
};
class C {
public:
C::C(bool class_a) {_class_a = _class_a;}
void func_c_1()
{
if(_class_a) a.func1();
else b.func1();
}
void func_c_2()
{
if(_class_a) a.func2();
else b.func2();
}
void func_c_3()
{
if(_class_a) a.func3();
else b.func3();
}
private:
bool _class_a;
A a;
B b;
};
Your code doesn't compile and I could be misunderstanding you completely but if you want a class which does different stuff depending on how it was created you might be helped by using a virtual base with pure virtual functions and deriving A and B from it overriding those virtual functions.
class Base
{
public:
virtual int func1() = 0;
virtual int func2() = 0;
virtual int func3() = 0;
virtual ~Base(){} //it is important that this is virtual
};
class A: public Base
{
public:
virtual int func1(){
//do something
}
virtual int func2(){
//do something
}
virtual int func3(){
//do something
}
};
class B: public A
{
public:
virtual int func1(){
//do something else
((A*)this)->func1(); //call A's func1()
}
virtual int func2(){
//do something else
}
virtual int func3(){
//do something else
}
};
Base *a = new A;
Base *b = new B;
Base *c = a;
c->func1(); //does something
c=b;
c->func1(); //does something else
Otherwise if you essentially want two different classes (with distinct types) you could use a template. If this is what you want comment and I will add example code.
It also should be noted that nothing is stopping you from using function pointers in C++ although I wouldn't recommend it. Here is an example code just for giggles:
#include <functional>
class A
{
public:
int func1(){
//do something
return 1;
}
int func2(){
//do something
return 1;
}
int func3(){
//do something
return 1;
}
};
class B
{
public:
int func1(){
//do something else
return 1;
}
int func2(){
//do something else
return 1;
}
int func3(){
//do something else
return 1;
}
};
class C
{
public:
C(bool useA)
{
if(useA) {
func1 = std::bind(&A::func1,a_);
func2 = std::bind(&A::func2,a_);
func3 = std::bind(&A::func3,a_);
}
else {
func1 = std::bind(&B::func1,b_);
func2 = std::bind(&B::func2,b_);
func3 = std::bind(&B::func3,b_);
}
}
std::function<int()> func1;
std::function<int()> func2;
std::function<int()> func3;
private:
A a_;
B b_;
};
C c(true);
C c2(false);
c.func1();
It looks to me like you're trying to understand inheritance in C++. Your code looks like it's trying to get different behavior depending on if you tell it to be a class A or a class B. If so, this should help:
#include <iostream>
using namespace std;
class A
{
public:
void foo() { cout << "A::foo\n"; }
void bar() { cout << "A::bar\n"; }
};
class B : public A
{
public:
void foo() { cout << "B::foo\n"; }
void fee() { cout << "B::fee\n"; }
};
main()
{
A* a = new A();
B* b = new B();
a->foo();
a->bar();
b->foo();
b->bar();
b->fee();
((a)b)->foo();
((a)b)->bar();
}
I make class A, and (publicly) make class B inherit from it. Within main, the first 5 lines show behavior you'd expect, but if you want the b object to act as an A, I just cast it to it, and it does. (If you run this code, you'll see that the final foo line emits A::foo.)
So the behavior is not forced at construction time. When you construct the object, B::foo overrides A::foo. But simply by casting to the superclass, you can access the original functions.
Note, if you want b.foo() to always emit "B::foo", set the foo function in A to virtual:
class A
{
public:
virtual void foo() { cout << "A::foo\n"; }
void bar() { cout << "A::bar\n"; }
virtual ~foo() { /* any destructor code for the base class */ }
};
In this case, whether you use b->foo() or ((A*)b)->foo(), the output will be "B::foo". The run time will work with the original type of the object, instead of with the type you cast it to. Important - As soon as you make any virtual function in your class, you must make a virtual destructor for that function. If you don't, only the base class's destructor will be called when your object is deleted. (When you use virtual destructors, each destructor is called from the most-derived class to the base, essentially unwinding the work that was done when the object was constructed.)
Hope this helps...
Why is it that in the code below the compiler complains that PureAbstractBase is an ambiguous base class of MultiplyInheritedClass? I realize I have two copies of the PureAbstractBase in MultiplyInheritedClass and that FirstConreteClass and SecondConreteClass should be derived virtually because they're the middle row of the diamond (and that does indeed fix the problem with the code below). But even though I have two copies of the interface why is it that the code in MultiplyInheritedClass does not just override both and unambiguously pick the interface class defined in MultiplyInheritedClass?
#include <iostream>
using namespace std;
class PureAbstractBase {
public:
virtual void interface() = 0;
};
// I know that changing the following line to:
// class FirstConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class FirstConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object FirstConcreteClass\n"; }
};
// I know that changing the following line to:
// class SecondConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class SecondConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object SecondConcreteClass\n"; }
};
class MultiplyInheritedClass : public FirstConcreteClass,
public SecondConcreteClass {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object MultiplyInheritedClass\n"; }
};
Further, why do I not have issues with the following hierarchy? Doesn't the ConcreteHandler class have three copies of the AbstractTaggingInterface in this case? So why doesn't it have the same issue as the example above?
#include <iostream>
using namespace std;
class AbstractTaggingInterface {
public:
virtual void taggingInterface() = 0;
};
class FirstAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "FirstAbstractHandler\n"; }
virtual void handleFirst() = 0;
};
class SecondAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "SecondAbstractHandler\n"; }
virtual void handleSecond() = 0;
};
class ThirdAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "ThridAbstractHandler\n"; }
virtual void handleThird() = 0;
};
class ConcreteHandler : public FirstAbstractHandler,
public SecondAbstractHandler,
public ThirdAbstractHandler {
public:
virtual void taggingInterface() = { cout << "ConcreteHandler\n"; }
virtual void handleFirst() {}
virtual void handleSecond() {}
virtual void handleThird() {}
};
I am trying to wrap my head around all of this because I had a conversation with a colleague recently where he claimed that if you were inheriting from pure virtual classes (interfaces) without any data members then virtual inheritance was not necessary. I think understanding why the former code example does not work and the latter does would go a long way to getting this straight in my head (and clear up what exactly he meant by his comment). Thanks in advance.
You need virtual inheritance to overcome the diamond-ambiguity:
class FirstConcreteClass : public virtual PureAbstractBase { ... };
class SecondConcreteClass : public virtual PureAbstractBase { ... };
Long-winded explanation: Suppose you have this:
// *** Example with errrors! *** //
struct A { virtual int foo(); };
struct B1 : public A { virtual int foo(); };
struct B2 : public A { virtual int foo(); };
struct C: public B1, public B2 { /* ... */ }; // ambiguous base class A!
int main() {
A * px = new C; // error, ambiguous base!
px->foo(); // error, ambiguous override!
}
The inheritance of the virtual function foo is ambiguous because it comes in three ways: from B1, from B2 and from A. The inheritance diagram forms a "diamond":
/-> B1 >-\
A-> ->C
\-> B2 >-/
By making the inheritance virtual, struct B1 : public virtual A; etc., you allow any baseclass of C* to call the correct member:
struct A { virtual int foo(); };
struct B1 : public virtual A { virtual int foo(); };
struct B2 : public virtual A { virtual int foo(); };
struct C: public B1, public B2 { virtual int foo(); };
We must also define C::foo() for this to make sense, as otherwise C would not have a well-defined member foo.
Some more details: Suppose we now have a properly virtually-inheriting class C as above. We can access all the various virtual members as desired:
int main() {
A * pa = new C;
pa->foo(); // the most derived one
pa->A::foo(); // the original A's foo
B1 * pb1 = new C;
pb1->foo(); // the most derived one
pb1->A::foo(); // A's foo
pb1->B1::foo(); // B1's foo
C * pc = new C;
pc->foo(); // the most derived one
pc->A::foo(); // A's foo
pc->B1::foo(); // B1's foo
pc->B2::foo(); // B2's foo
pc->C::foo(); // C's foo, same as "pc->foo()"
}
Update: As David says in the comment, the important point here is that the intermediate classes B1 and B2 inherit virtually so that further classes (in this case C) can inherit from them while simultaneously keeping the inheritance from A unambiguous. Sorry for the initial mistake and thanks for the correction!
Your first example fails because the compiler cannot disambiguate between the three implementations of implementation(). You are overriding that method in MultiplyInheritedClass, which actually overrides both FirstConcreteClass::implementation and SecondConcreteClass::implementation (once virtual, always virtual). However, both virtual calls still exist in the interface of MultiplyInheritedClass, which makes the call ambiguous at the call site.
The reason that your example works without virtual inheritance is that there is no conflicting implementation of the common base class. Put another way:
class Base
{
public:
void DoSomething() {
std::cout << "TADA!";
}
}
class One : public Base
{
//...
}
class Two : public Base
{
//...
}
class Mixed : public One, public Two
{
//...
}
int main()
{
Mixed abc;
abc.DoSomething(); //Fails because the compiler doesn't know whether to call
// One::DoSomething or Two::DoSomething, because they both
// have implementations.
//In response to comment:
abc.One::DoSomething(); //Succeeds! You removed the ambiguity.
}
Because your example has all pure virtual functions, there's no multiple implementations which the compiler needs to disambiguate. Therefore, only one implementation exists, and the call is unambiguous.
I tried both of the question codes and they worked fine when instantiating an object of the multi-inherited class. It didn't work only with polymorphism, like this for example:
PureAbstractBase* F;
F = new MultiplyInheritedClass();
And the reason is clear: it doesn't know to which copy of the Abstract base class it should be linked (sorry for bad expressions, I understand the idea but can't express it). And since inherting virtaully makes only one copy exist in the derived class, then it's fine.
Also the code of Billy ONeal is not clear at all, what should we place instead of the comments?
If we place:
public:
void DoSomething()
{ std::cout << "TADA!"; }
it works fine, because of no virtuality.
I work on Visual Studio 2008.
Why not do it like this (suggested in Benjamin Supnik's blog entry):
#include <iostream>
class PureAbstractBase {
public:
virtual void interface() = 0;
};
class FirstConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { std::cout << "Fisrt" << std::endl; }
};
class SecondConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { std::cout << "Second" << std::endl; }
};
class MultiplyInheritedClass : public FirstConcreteClass,
public SecondConcreteClass
{
public:
virtual void interface() { implementation(); }
private:
void implementation() { std::cout << "Multiple" << std::endl; }
};
int main() {
MultiplyInheritedClass mic;
mic.interface();
FirstConcreteClass *fc = &mic; //disambiguate to FirstConcreteClass
PureAbstractBase *pab1 = fc;
pab1->interface();
SecondConcreteClass *sc = &mic; //disambiguate to SecondConcreteClass
PureAbstractBase *pab2 = sc;
pab2->interface();
}
which gives:
Multiple
Multiple
Multiple
This way:
no virtual bases are involved (do you really need them?)
you can call the overriden function via a an instance of the MultiplyInheritedClass
ambiguity is removed by a two-stage conversion