This question already has answers here:
Double inheritance of enable_shared_from_this
(3 answers)
Closed 2 years ago.
When I try to run this code I get bad_weak_ptr exception:
using namespace std;
class O {
public:
O() {}
};
class A : public std::enable_shared_from_this<A>, virtual public O {
public:
A() {}
};
class B : public std::enable_shared_from_this<B>, virtual public O {
public:
B() {}
void GetShared() {
shared_from_this();
}
};
class C : public A, public B {
public:
C() {}
};
int main()
{
std::shared_ptr<B> pt = std::make_shared<C>();
pt->GetShared();
}
I would like to create instance of C class but then return B shared_ptr because that is what other interface requires. Is there a way to fix this code ? I cannot seem to do that.
Well as far as I know you are trying to do the undoable:
Inheritance in C++ means that you also include the same members of the parent classes. However for class C that would mean 2 classes that are already supposed to be held by a std::shared_ptr. But by the inheritance you tell the compiler that C should contain sub instances of A and B not held by a std::shared_ptr. shared_from_this will complain about this fact at run time by a bad weak ptr exception.
Probably you want C to be held only by a std::shared_ptr, then you can to the attached code.
If you simply want to "up-cast" a instance of C i.e. use it as it would be a class of B you can simply use a B& or use std::shared_ptr with out std::enables_shared_from_this or only on the up most class.
#include <memory>
using namespace std;
class O {
public:
O() {}
};
struct A : virtual public O {
};
struct B : virtual O {
B() {}
void GetShared() {
}
};
struct C : std::enable_shared_from_this<C>, A, B {
C() = default;
};
int main()
{
std::shared_ptr<B> pt = std::make_shared<C>();
pt->GetShared();
}
Related
I'm having trouble with C++ classes and inheritance right now...
Let's say we have
Class A {
A(string name);
~A();
void func(void);
}
Class B : public A {
B(string name);
~B();
...
}
Class C : public A {
C(string name);
~C();
...
}
Class D : public B, public D {
D(string name);
~D();
...
}
Whenever I create D, it calls the constructor for B and the one for C which results in multiple instances of A. The compiler then says it doesn't know which "func" it should call, the one from B or the one from C.
I would like to know how to call A constructor ONLY ONCE and then use it to build B and C.
I already tried using B::func() to be able to call func() but has I must have a cout in the class A builder. It results in wrong output.
This is called the diamond inheritance pattern.
In order to avoid having 2 instances of A in D, you need to use virtual inheritance.
When classes e.g. B virtually inherit A, it means that A will be present only once in a class derived from those classes.
Note: in this case it is the responsibility of the most derived class to initialize the virtual base(s) - as shown below.
The output from the following code demonstrates it:
#include <iostream>
#include <string>
class A {
public:
A(std::string const & name) { std::cout << "A::A\n"; };
~A() {};
void func(void);
};
//--------vvvvvvv-----------
class B : virtual public A {
public:
B(std::string const& name) : A(name) { std::cout << "B::B\n"; };
~B() {};
};
//--------vvvvvvv-----------
class C : virtual public A {
public:
C(std::string const& name) : A(name) { std::cout << "C::C\n"; };
~C() {};
};
class D : public B, public C {
public:
//-------------------------------vvvvvvv---------------------------------------------
D(std::string const& name) : A(name), B(name), C(name) { std::cout << "D::D\n"; };
~D() {};
};
int main()
{
D d("aaa");
}
Output:
A::A
B::B
C::C
D::D
I.e. A is present once in D.
Note that if you remove the virtual keyword, the output will be:
A::A
B::B
A::A
C::C
D::D
I.e. A is present twice in D (as you observed).
Some side notes:
Better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
Your code contains many typos: Class should be class, missing ; at the end of classes.
You constructors can accept the name by const & as demonstrated in my code, to avoid copy.
I'm learning C++ OOP. I don't understand a principle, and I don't know what to google to find an answer.
If I have this:
#include <iostream>
class A
{
public:
int a;
A() : a(1){}
};
class B : virtual public A
{
public:
B() {this->a = 2;}
};
class C : virtual public A
{
public:
C() {this->a = 3;}
};
class D : public B, public C
{
public:
D() {this->a = B::a;}
};
int main()
{
D test;
std::cout << test.a << std::endl;
}
I expect the output to be 2 since I want the value of the inherited B class in the D class. It seems to me like the value of the C class is taken, because that constructor gets called last and overwrites the B::a value, is that right?
How would I go about getting values from the B class inside the D class?
This question already has answers here:
How does virtual inheritance actually work?
(1 answer)
Internal mechanism of virtual inheritance
(1 answer)
How does virtual inheritance solve the "diamond" (multiple inheritance) ambiguity?
(5 answers)
How C++ virtual inheritance is implemented in compilers?
(5 answers)
Closed 11 months ago.
Consider the following code:-
#include<iostream>
using namespace std;
class A
{
public:
int a;
A()
{
a = 10;
cout<<"Address of a in A "<<&a<<endl;
}
};
class B : public virtual A {
public:
B()
{
cout<<"Address of a in B "<<&a<<endl;
}
};
class C : public virtual A {
public:
C()
{
cout<<"Address of a in C "<<&a<<endl;
}
};
class D : public B, public C {
public:
D()
{
cout<<"Address of a in D "<<&a<<endl;
}
};
int main()
{
A a;
B b;
C c;
D d;
return 0;
}
So, here when we create an object of D class, Constructors are called in this order A()->B()->C()->D().
Here A() is not called again before C() because we had made use of virtual keyword, which is preventing the constructor A() to be called again.
** Question: 1 But, I wanted to know what is happening in background in code when we are using the virtual keyword?
Question 2 And is variable a in class A and class B point to same memory location?
Question 3 And why this variable's memroy address differs in class C when A is not made virtual from the address of that variable in B?**
//In file1.hpp
class A
{
protected:
class B
{
public:
B () {};
};
};
// In file2.hpp
class C
{
public:
void getValue()
{
D obj; ---- error: no matching function for call to D
printf("%d\n",obj.c);
}
class D : public A::B
{
friend class C; -- I tried writing this but still no luck.
public:
D(int a, int b) : c(a), d(b) {}
virtual ~D() {}
//something
private:
int c; int d;
};
class E : public D
{
E() : D(1,2) {}
virtual ~E() {}
};
}
int main()
{
C::E obj;
}
In the public function, getValue I want to access the private member variables of the class D which are (c and d). How can I do that? I tried putting "friend class C" inside class D and then tried creating an object of class D inside getValue function but instead of getting a value like c=5 or d=6, I always get 0.
If I print the value in the following area, I get the correct value. I won't be able to show you how getValue is called but just imagine that it is called somehow. I just need to print c,d in that.
D(int a, int b)
: c(a), d(b) {};
EDIT: At the time of instantiation in getValue, I do something like this
D obj; --- error: no matching function for call to D
Let take the following example:
#include <iostream>
//In file1.hpp
class A
{
protected:
class B
{
public:
B () = default;
};
friend class C; // <-- bad idea
};
// In file2.hpp
class C
{
public:
void getValue()
{
// Creating an object E?
E objE;
// Access c and d
std::cout << "c:" << objE.c << ", d:" << objE.d << std::endl;
}
class D : public A::B // <-- bad idea?
{
public:
D(int a, int b): c(a), d(b) {}
virtual ~D() {}
//something
private:
int c; // dangerous to not initialize basic types
int d;
friend class C; // <-- bad idea
};
class E : public D
{
public:
E() : D(1,2) {}
virtual ~E() {}
};
};
int main()
{
C objC;
objC.getValue();
}
( you can run it here: https://onlinegdb.com/hNfm7Pvg0f )
First is, to have an instance of E to access in C::getValue, so I instantiated an object.
private and protected indicate that those properties and methods are not available publicly (encapsulation) and that is exactly what you are trying to do. You can make exceptions with friend keyword, but that is rarely a good idea (I probably use it twice in my 20 years carrier). But hey! it works.
Hi I have a derived class and I want to pass the pointer of the derived class object to the base class.
I am getting segmentation fault while running the code.
#include <iostream>
using namespace std;
class A {
public:
virtual void x() = 0;
A* a;
};
class B: public A {
public:
B(A* x) {
a = x;
}
void x () {}
};
class C: public B {
public:
C() : B(new C) { }
};
int main() {
C c;
return 0;
}
Can someone help me suggest a way to achieve this or help me in fixing the code.
I believe you want to pass a pointer to current object. This is what this is for.
C() : B(this) { }