Although I made the members of both base and derived classes public, Why does the conversion says that it is inaccessible?
class B
{
public:
int var;
};
class D: private B
{
public:
int var;
};
int main()
{
D d;
Base &b = d; //my error
}
You can't convert from a derived class to a non-public base class (well, outside the class itself anyway). Private inheritance is typically used as a form of composition, not for substitution so there's no need to convert to the base. In your case it looks like you want substitution so you should use public inheritance.
Try this:
#include <iostream>
class B
{
public:
int var;
};
class D: public B
{
public:
int var;
};
int main()
{
D d;
B &b = d; //my error
}
What you are trying to do won't work with private inheritance. Also note that your base class is known as B and not Base.
Regards,
Dennis M.
Related
From what I have learnt about virtual inheritance, whenever we have a class A (the base class), classes B, C, D (all these three virtually inherit class A) then if there is a class derived which inherits from B, C and D classes is instantiated then only a single object of class A would be created.
I tried to reason about the virtual inheritance by taking different cases:
Case 1:
Assume the derived class inherits only from class B and C. Even then only a single object of class A gets instantiated, right?
I tried to verify this using this code and it certainly seems to be the case:
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B: virtual public A
{
public:
int b;
};
class C: virtual public A
{
public:
int c;
};
class D: virtual public A
{
public:
int d;
};
class derived: public B, public C
{
public:
int y;
};
int main()
{
derived dObj;
cout<<&(dObj.B::a)<<'\n';
cout<<&(dObj.C::a)<<'\n';
return 0;
}
Output:
0x7ffc8adac1c0
0x7ffc8adac1c0
Case 2:
Assume the derived class inherits from class B, C and D, but class D doesn't inherit class A virtually. In this case, 2 objects of class A get instantiated, right? - One for B, C and one for D.
I tried to verify this using this code and it certainly seems to be the case:
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B: virtual public A
{
public:
int b;
};
class C: virtual public A
{
public:
int c;
};
class D: public A
{
public:
int d;
};
class derived: public B, public C, public D
{
public:
int y;
};
int main()
{
derived dObj;
cout<<&(dObj.B::a)<<'\n';
cout<<&(dObj.C::a)<<'\n';
cout<<&(dObj.D::a)<<'\n';
return 0;
}
Output:
0x7ffd512429c8
0x7ffd512429c8
0x7ffd512429bc
Now here is my question:
Are my observations correct? That is, instead of just 3 classes - B, C, D, let's assume we have n classes that inherit class A, if out of them, m (1<=m<=n) classes are inherited by another class named derived, and if out of those m classes only k (0<=k<=m) classes inherit class A virtually then the number of objects of class A that get instantiated when instantiating the derived class would be = 1+m-k (if k!=0) and m (when k=0), right?
From the content written in the cppreference website it is indeed the case:
See the first example under the virtual base classes section.
From https://en.cppreference.com/w/cpp/language/dynamic_cast:
dynamic_cast < new_type > ( expression )
3) If new_type is a pointer or reference to Base, and the type of expression is a pointer or reference to Derived, where Base is a unique, accessible base class of Derived, the result is a pointer or reference to the Base class subobject within the Derived object pointed or identified by expression. (Note: an implicit conversion and static_cast can perform this conversion as well.)
Sample code:
#include <iostream>
using namespace std;
class A {
//public:
// virtual ~A() {
//
// }
};
class B : public A {
};
class C : public B {
};
class D : public B, public A {
};
int main()
{
D* pd = new D;
if (B* pa = dynamic_cast<B*>(pd)) {
cout << "1";
}
return 0;
}
No error or warning under VC++
warning: direct base 'A' inaccessible in 'D' due to ambiguity under gcc, link
Shouldn't I expect a compile error?
Now I find that if I try to convert D* to A*, a error would occur, but as mentioned above, from D* to B*, no error.
int main()
{
D* pd = new D;
if (A* pa = dynamic_cast<A*>(pd)) {
cout << "1";
}
return 0;
}
link
In that context, unique means that Derived contains new_type only once, not that Derived derives from a single base class.
So, in your example, B is unique, because D contains it only once.
In your example, D contains A twice (once directly, and once through B), so a cast to A cannot be made, as A is not unique.
Note, that "containment" what it counts. So, in this example, C derives from Base twice, yet it is fine, as Base is inherited with the keyword virtual:
struct Base { };
struct A: virtual Base { };
struct B: virtual Base { };
struct C: A, B { };
int main() {
C c;
dynamic_cast<Base &>(c);
}
(If I haven't used virtual, then Base would have been ambiguous)
Note: I'd use static_cast instead, as it can do the cast in this case as well. Using dynamic_cast is a little bit misleading here, as the cast will be done compile-time, and not run-time.
The warning causes by indirect base class issue in multiple-inheritance model. D has two copies of base class A, one directly and one indirectly via B. When a base class is specified as a virtual base (same as #geza example), there is only one copy of base class' data members shared between virtual base classes.
class A {
public:
A() {}
};
class B : virtual public A {
public:
B() : A() {}
};
class C : public B, virtual public A {
public:
C() : B() {}
};
int main()
{
A* pa = static_cast<A *>(new C()); // no more warning since A is virtual
return 0;
}
It's well explained here: Multiple Base Classes.
The following code is giving me the error that 'A' is an inaccessible base of 'B' and I am not sure why:
class A {};
class B : protected A {};
A foo( A a );
///
B b;
foo(b);
Any explanation for this much appreciated.
Edit: I suppose I am just confused about the nature of protected inheritance. I thought it meant that any derived class (in this case of A) could inherit its variables and its functions.
A class that inherits the protected parent class can get to it, otherwise it is considered private:
class A {};
class B : protected A {};
A foo(A a) { return a; };
class C : public B {
public:
A foo(C c) { return c; };
};
int main() {
B b;
//foo(b); // Can't implicitly convert, A is protected (might as well be private from this line's perspective)
C c;
A a = c.foo(c); // class C can get A
}
I am put/get value in/from subclass B from object of base class A. But I am not able to assign or get the value. My code is:
class A
{
};
class B: A
{
string SID;
};
class C: A
{
string Name;
};
class D : A
{
string Name;
};
class E
{
A a;
UINT32 AccessLevel;
};
.......
main()
{
E e;
}
Using object of e am trying to get the value of subclass B.
I need to get the SID from the class B?
Thanks,
The C++11 standard 11/3 says:
Members of a class defined with the keyword class are private by default.
at 11.2/2
In the absence of an access-specifier for a base class [...] private is assumed when the class is defined with the class-key class.
and at 11.2/1:
If a class is declared to be a base
class for another class using the private access specifier, the public and protected members of the base
class are accessible as private members of the derived class.
So what does that mean? First of all:
class A {};
class B : A {};
Here A, by virtue of 11.2/2 is inherited privately. This may be okay if you want to inherit variables and you want to implement getter/setters for a variable only in a derived class, but that's usually considered bad style.
In your case however, as stated by 11/3, your members are not inherited at all because they are private members:
class A
{
public:
int a; // inherited
protected:
int b; // inherited
private:
int c; // NOT inherited
};
and especially
class A { int a; };
is equivalent to
class A { private: int a; };
So you could make your members accessable from within your derived classes by making them public or protected (see 11.2/1):
class A { public: int a; };
class B : A {}; // privately inherits a
and if you wanted to make it acessable from outside of your derived classes you will have to inherit as public as well:
class A { public: int a; };
class B : public A {}; // publicly inherits a
but that's not what you usually would do. It's considered better style to make variables private and expose only getters and setters for those:
class A
{
public:
int get_a() const { return a_; }
void set_a(int val) { a_ = val; }
private:
int a_;
};
class B : public A {}; // now publicly inherits the getters and setters
// but not a_ itself
Why does the follwing code produce this error even though c is a struct and has a public inheritance by default??
struct c
{
protected:
int i;
public:
c(int ii=0):i(ii){}
virtual c *fun();
};
c* c::fun(){
cout<<"in c";
return &c();
}
class d : c
{
public:
d(){}
d* fun()
{
i = 9;
cout<<"in d"<<'\t'<<i;
return &d();
}
};
int main()
{
c *cc;
d dd;
cc = ⅆ
cc->fun();
}
You need:
class d : public c
class inheritance is private by default.
When you privately inherit from a class or a struct, you explicitly say, among other things, that direct conversion from a derived type to a base type isn't possible.