Inheriting a constructor from a private template class in C++ - c++

Why does class D compile, but class C does not?
class A
{
public:
A(int) {}
};
template <class T>
class B : private T // Note: private base class
{
public:
using T::T;
};
class C : public B<A>
{
public:
C() : B<A>(123) {} // Error: 'class A A::A' is inaccessible
}; // within this context
using BA = B<A>;
class D : public BA
{
public:
D() : BA(123) {} // OK
};
I tested with GCC, Clang and Visual C++, and they are all the same.
Changing class B : private T to public T solves the problem. But why? (Note that the using T::T is public.)

Class A contains the injected-class-name A within its scope (that is, A::A refers to class A unless it happens to refer to the constructor).
Class B inherits this, so the name A within the scope of B refers to the injected-class-name A in scope of A. However, since A is a private base class of B, all names in scope of A are private within B.
Class C again inherits this, but it cannot access this A, since it is private within B. Hence the error. Note that the error is actually with using the name A in the construct B<A>.
Class BA doesn't have this problem, since the definition B<A> is not in the scope of any class, so the name A refers to the global name A and not to any injected-class-name. And of course, the name BA is public.
You can easily solve this by qualifying the name A in C:
class C : public B<A>
{
public:
C() : B<::A>( 123 ) {}
};
Note that constructor inheritance has no effect there. The problem is with access to the class name A (injected in A and inherited in B and C), not with access to the constructor.

Related

How can I use a private parent class as a parent of an internal class?

How can I use a private parent class as a parent of an internal class?
I'm try to do this:
class A
{
};
class B : private A
{
};
class C : private B
{
public:
class D : public A
{
};
};
int main()
{
C c;
}
But I'm getting the following error. Is there any way to work around it, or do I need to change the private to protected?
test.cpp:14:20: error: 'A' is a private member of 'A'
class D : public A
^
test.cpp:6:11: note: constrained by private inheritance here
class B : private A
^~~~~~~~~
test.cpp: 1: 7: note: member is declared here
class A
^
1 error generated.
The compiler thinks you are trying to refer to C's parent's parent's type. Specify the type of A completely to avoid this ambiguity. Use :: to denote the global namespace.
class C : private B
{
public:
class D : public ::A
// Add this ^^
{
};
};
This is a case of Injected class name.
For the name of a class or class template used within the definition of that class or template or derived from one, unqualified name lookup finds the class that's being defined as if the name was introduced by a member declaration (with public member access)

C++ Multilevel Inheritance, Polymorphism

Suppose i have three classes A, B and C. class B inherits from class A and the inheritance is private whereas class C inherits from B and the inheritance is public. Now class A has a protected function which class C wants to access. So, what must be done in class B to make that protected function available to class C.
Here is the link to the code : http://pastebin.com/9E2sLZzj
The "using" keyword makes a member of an inherited class visible, and resolvable, in the scope of its subclass. So, to make the privately-inherited member available to B's subclasses:
class A {
protected:
void foo() {}
};
class B : private A {
protected:
using A::foo;
};
class C : public B {
void bar()
{
foo();
}
};
Okay i got the solution
This code fragment worked after inserting it into Class B.
int get(){
return A::get();
}
Not sure what it does though

virtual inheritance and base class of base class

Consider the following code:
class A {
};
class B : public A {
};
class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};
In this case GCC (4.8.1, C++99) gives me the correct error (I understand this behavior):
prog.cpp:12:8: error: type ā€˜aā€™ is not a direct base of ā€˜cā€™
However if the inheritance between b and a is virtual, this does not happen:
class A {
};
class B : virtual public A {
};
class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};
Why does this work?
Is A now considered a direct base to C by the compiler?
In general, because this is how C++ tries to resolve the diamond inheritance problem http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (whether or it is a good or bad solution is left as an exercise to the reader).
All inheritance is a combination of an is-a and a has-a relationship...you must instantiate an instance of the parent. If you have the following classes:
class a;
class b : a;
class c : a;
class d : b,c;
Then you've instantiated an a for each b and c. d will not know which a to use.
C++ solves this by allowing virtual inheritance, which is high-overhead inheritance that allows b and c to share the same a if inherited in d (it is much more complicated than that, but you can read up on that on your own).
The most derived type in the chain needs to be able to override the instantiation of the shared class to control disparities in the way that the shared class is inherited in the parent classes. Take the following example:
class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}
If d did not define what a was instantiated as, it would have definitions for conflicting instantiations (from b and c). C++ handles this by forcing the most derived class in the inheritance chain to instantiate all parent classes (the above would barf if d did NOT explicitly instantiate a, though if a supplied a default constructor that could be implicitly used) and ignoring all parent instantiations.
Why does this work?
According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type".
Virtual base is shared between all classes that derive from it for the instance of the object. Since a constructor may only be called once for a given instaniation of an object, you have to explicitly call the constructor in the most derived class because the compiler doesn't know how many classes share the virtual base. This is because the compiler will start from the most base class's constructor and work to the most derived class. Classes that inherit from a virtual base class directly, will not, by the standard, call their virtual base classes constructor, so it must be called explicitly.
From N3337, 12.6.2
Initializing bases and members
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Perhaps someone who has better version of Standard can verify this.

Private base class accessibility in C++

I recently had to do something like this:
class A { };
class B : private A { };
class C : public B {
public:
A *myA;
};
int main() {
return 0;
}
And I get an error in the three compilers I tried. When I changed the declaration of myA to ::A *myA everything works ok. I poked around in the C++ standard and found Section 11.2, paragraph 3 where it says:
Note: A member of a private base class might be inaccessible as an inherited member name, but accessible directly.
Which is relevant, but unclear. Why is the name A inaccessible? What problems would occur if A was not hidden?
Thanks,
-Ben
Where it could "go wrong":
namespace nmsp
{
class A {};
}
class A {};
class B : private nmsp::A
{
// well-formed:
A* d; // refers to the injected-class-name nmsp::A!!
};
class C : public B
{
// ill-formed
A* p; // refers to the injected-class-name nmsp::A!!
};
It should not depend on the access-specifier in the base-clause whether ::A or nmsp::A is used, otherwise it'd be error-prone IMO.

C++ reference sub class in super class

I am little bit confused on referencing a sub class inside a super class in C++.
For example, given Java :
public class Entity {
protected ComplexEntity _ce;
public Entity() {
}
public ComplexEntity getCentity() {
return _ce;
}
}
Where ComplexEntity extends the entity.It works.In the sub class I call getCentity() no errors.
Now ,in C++ when I write something like that:
#pragma once
#include "maininclude.h"
#include "ExtendedEntity.h"
using namespace std;
class EntityBase
{
public:
EntityBase(void);
EntityBase(const string &name);
~EntityBase(void);
protected:
ExtendedEntity* _extc;
string _name;
};
I am getting compiler error:
error C2504: 'Entity' : base class undefined
In the classes which inherit from this Entity.Why does that happen?
Is it completely unacceptable in C++?
May be Entity must be abstract ?
I would like to get suggestions on possible workarounds.
You may consider using CRTP, cut/paste from Wikipedia:
// The Curiously Recurring Template Pattern (CRTP)
template<class Derived>
class Base
{
Derived* getDerived() { return static_cast<Derived*>(this); }
};
class Derived : public Base<Derived>
{
// ...
};
Your code is like the following:
struct D : B {}; // error: B doesn't mean anything at this point
struct B {
D *d;
};
Your header ExtendedEntity.h is trying to use the definition of Entity before Entity is defined.
You need to change your code to this:
struct D;
struct B {
D *d;
};
struct D : B {};
A class in C++ needs to know the size of all its members and of all its superclasses. Class Entity does not know the size of it's subclass ComplexEntity, unless class ComplexEntity is defined before class Entity. But then, class ComplexEntity does not know the size of its superclass Entity.
This problem exists in C++, because class members are accessed using simple offset calculation. You can work around this, by forward declaring the derived class and using pointers as members:
class Extended; // declare the derived class
class Base { // define the base class
Extended* e; // you cannot use Extended e here,
// because the class is not defined yet.
};
class Extended : public Base {}; // define the derived class