So private members in the base class are also in the inherited class but not accessible in it, right?
Are they actually in the memory allocated to the the inherited object?
Are they actually in the memory allocated to the the inherited object?
Yes, they need to exist. The private members are part of the implementation detail of the base class. Without them, in general, the base class wouldn't be able to function (which is why they exist in the first place).
Making them private just allows the base class to create its implementation however it chooses, without exposing that to anybody, including the subclass.
Yes. Just for example, you can use a public function from the base class that manipulates private data, even in an instance of the derived class:
class Base {
int x;
public:
Base() : x(0) {}
void inc() { ++x; }
void show() { std::cout << x << "\n"; }
};
class Derived : public Base {
};
int main() {
Derived d;
d.show();
d.inc();
d.show();
}
With a properly functioning compiler, this must display:
0
1
...showing that the data in the Base object is present in the Derived object, even though it's not (directly) accessible.
Of course with almost anything in C++, there's the "as-if" rule -- if the compiler can determine that it can somehow produce the correct observable behavior for the program, even without including the private part(s) of the base class, then it's free to do so. The most obvious example of this would be if you included something (member function or data) in the base class that was simply never used in practice.
Yes they are,
When object of the derived class is being constructed all of its base classes are first being constructed as well.
Consider this example:
class Base
{
int x;
public:
Base(int px)
: x(px)
{
}
};
class Derived : public Base
{
int y;
public:
Derived(int px, int py)
: y(py), Base(px)
{
}
};
This example compiles and works and Base is initialized (constructor is called) before you reach the body of the Derived constructor.
Related
#include <iostream>
class Base
{
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); // This does not compile
somethingProtected(); // But this is fine
}
};
int main()
{
Derived d;
d.somethingDerived();
return 0;
}
I thought that maybe only the protected members of this can be used and protected members of other instances are forever unreachable.
But:
class Derived : public Base
{
public:
void somethingDerived(Derived& d)
{
d.somethingProtected(); // This compiles even though d is
// potentially a different instance
}
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
}
};
I feel kind of nauseated by this, since I have been programming in C++ for some time, but I could not find any explanation for this behaviour.
EDIT:
It doesn't matter if it is the same or a different instance:
int main()
{
Derived d1, d2; // Two different instances
d1.somethingDerived(d2); // This compiles fine
d1.somethingDerived(d1); // This compiles fine
return 0;
}
EDIT2:
It seems that when it comes to access rights, it doesn't matter at all what instance of a class is being used:
class Base
{
public:
void something(Base& b) // Another instance
{
++b.a; // But can enter private members
}
private:
int a;
};
Even though access control in C++ works on per-class basis (as opposed to per-instance basis), protected access specifier has some peculiarities.
The language specification wants to ensure that you are accessing a protected member of some base subobject that belongs to the derived class. You are not supposed to be able access protected members of some unrelated independent objects of base type. In particular, you cannot access protected members of freestanding objects of base type. You are only allowed to access protected members of base objects that are embedded into derived objects as base subobjects.
For this reason, you have to access protected members through pointer->member syntax, reference.member or object.member syntax, where the pointer/reference/object refers to the derived class.
This means that in your example, protected member somethingProtected() is not accessible through Base objects, Base * pointers or Base & references, but it is accessible through Derived objects, Derived * pointers and Derived & references. Your plain somethingProtected() access is allowed, since it is just a shorthand for this->somethingProtected() where this is of type Derived *.
b.somethingProtected() violates the above requirements.
Note that in accordance with the above rules in
void Derived::somethingDerived()
{
Base *b = this;
b->somethingProtected(); // ERROR
this->somethingProtected(); // OK
}
the first call will also fail while the second one will compile, even though both are trying to access the same entity.
I believe you have some confusion on how to access base class members.
It is only this way:
class Derived : public Base
void drivedMethod() {
Base::baseMethod();
}
in your example you are trying to access a protected member of another instance.
a Derived instance will have access to it's own protected members but not to another class instance protected members, this is by design.
In fact accessing the protected members of another class, from another instance members or from the main function are in fact both under public access...
http://www.cplusplus.com/doc/tutorial/inheritance/
(look for the access specifier table to see the different levels)
Both examples prove the same thing for example:
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
here your Derived class is getting b as a parameter, so it is getting another instance of base, then because b.somethingProtected is not public it will not complie..
this will complie:
void somethingDerived()
{
Base::somethingDerived();
your second example complies fine because you are accessing a public method on another d class
> void somethingDerived(Base& b)
> {
> b.somethingProtected(); // This does not
> }
The Derived class can only access the protected base member in Derived objects. It cannot access the member in objects that are not (necessarily) Derived objects. In the cases that fail, you are trying to access the member via a Base &, and since this might refer to an object that is not Derived, the access can't be made.
What you have done is illegal in C++. A protected member can not be accessed by an object of a class. Only member functions can access protected members. protected members behave just like private members except while inherited by a derived class. Consider the program given below to understand the difference between private, public and protected members.
class Base
{
private:
void somethingPrivate()
{
std::cout << "sasa" << std::endl;
}
public:
void somethingPublic()
{
std::cout << "haha" << std::endl;
}
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingPublic(); // Works fine.
somethingProtected(); // This is also fine because accessed by member function.
//b.somethingProtected(); // Error. Called using object b.
//somethingPrivate(); // Error. The function is not inherited by Derived.
}
};
Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!
Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?
Looking at your design, I see one cannot call derived::a directly, but only through a base interface.
Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given
derived d;
while d.a() wouldn't compile, we can always do
base & b = d;
b.a(); //which actually calls derived::a
In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.
Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.
Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
Thus a derived class could be like:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
and no other class can call them, unless it extended base itself:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.
If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.
The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.
Consider the template method pattern:
struct base {
void foo() { a() ; b(); }
virtual void a() = 0;
virtual void b() = 0;
};
struct derived : base {
private:
void a() override {}
void b() override {}
};
int main()
{
derived().foo();
}
Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.
#include <iostream>
class Base
{
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); // This does not compile
somethingProtected(); // But this is fine
}
};
int main()
{
Derived d;
d.somethingDerived();
return 0;
}
I thought that maybe only the protected members of this can be used and protected members of other instances are forever unreachable.
But:
class Derived : public Base
{
public:
void somethingDerived(Derived& d)
{
d.somethingProtected(); // This compiles even though d is
// potentially a different instance
}
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
}
};
I feel kind of nauseated by this, since I have been programming in C++ for some time, but I could not find any explanation for this behaviour.
EDIT:
It doesn't matter if it is the same or a different instance:
int main()
{
Derived d1, d2; // Two different instances
d1.somethingDerived(d2); // This compiles fine
d1.somethingDerived(d1); // This compiles fine
return 0;
}
EDIT2:
It seems that when it comes to access rights, it doesn't matter at all what instance of a class is being used:
class Base
{
public:
void something(Base& b) // Another instance
{
++b.a; // But can enter private members
}
private:
int a;
};
Even though access control in C++ works on per-class basis (as opposed to per-instance basis), protected access specifier has some peculiarities.
The language specification wants to ensure that you are accessing a protected member of some base subobject that belongs to the derived class. You are not supposed to be able access protected members of some unrelated independent objects of base type. In particular, you cannot access protected members of freestanding objects of base type. You are only allowed to access protected members of base objects that are embedded into derived objects as base subobjects.
For this reason, you have to access protected members through pointer->member syntax, reference.member or object.member syntax, where the pointer/reference/object refers to the derived class.
This means that in your example, protected member somethingProtected() is not accessible through Base objects, Base * pointers or Base & references, but it is accessible through Derived objects, Derived * pointers and Derived & references. Your plain somethingProtected() access is allowed, since it is just a shorthand for this->somethingProtected() where this is of type Derived *.
b.somethingProtected() violates the above requirements.
Note that in accordance with the above rules in
void Derived::somethingDerived()
{
Base *b = this;
b->somethingProtected(); // ERROR
this->somethingProtected(); // OK
}
the first call will also fail while the second one will compile, even though both are trying to access the same entity.
I believe you have some confusion on how to access base class members.
It is only this way:
class Derived : public Base
void drivedMethod() {
Base::baseMethod();
}
in your example you are trying to access a protected member of another instance.
a Derived instance will have access to it's own protected members but not to another class instance protected members, this is by design.
In fact accessing the protected members of another class, from another instance members or from the main function are in fact both under public access...
http://www.cplusplus.com/doc/tutorial/inheritance/
(look for the access specifier table to see the different levels)
Both examples prove the same thing for example:
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
here your Derived class is getting b as a parameter, so it is getting another instance of base, then because b.somethingProtected is not public it will not complie..
this will complie:
void somethingDerived()
{
Base::somethingDerived();
your second example complies fine because you are accessing a public method on another d class
> void somethingDerived(Base& b)
> {
> b.somethingProtected(); // This does not
> }
The Derived class can only access the protected base member in Derived objects. It cannot access the member in objects that are not (necessarily) Derived objects. In the cases that fail, you are trying to access the member via a Base &, and since this might refer to an object that is not Derived, the access can't be made.
What you have done is illegal in C++. A protected member can not be accessed by an object of a class. Only member functions can access protected members. protected members behave just like private members except while inherited by a derived class. Consider the program given below to understand the difference between private, public and protected members.
class Base
{
private:
void somethingPrivate()
{
std::cout << "sasa" << std::endl;
}
public:
void somethingPublic()
{
std::cout << "haha" << std::endl;
}
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingPublic(); // Works fine.
somethingProtected(); // This is also fine because accessed by member function.
//b.somethingProtected(); // Error. Called using object b.
//somethingPrivate(); // Error. The function is not inherited by Derived.
}
};
I am using a class say baseClass, from which I derive another class derivedClass. I have a problem definition that says, apart from others:
i) A member - object initialiser should be used to initialise a data member, say var1, that is declared in the base class.
ii) i) is done inside a base class constructor. It says, this has to be invoked only via a derived class constructor.
iii) The base class is an abstract class, whose objects cannot be created. But, I have a third class, inside which, I use:
baseClass *baseObjects[5];
The compiler does not report an error.
I do not understand, what i) and ii) really mean. An explanation in simple words would be fine. Also, any assistance on iii) is welcome.
Question 1:
Read about constructors : http://www.cprogramming.com/tutorial/constructor_destructor_ordering.html
Question 2:
Read about initialization list:
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
Question 3:
Read about pointers to derived class:
http://www.learncpp.com/cpp-tutorial/121-pointers-and-references-to-the-base-class-of-derived-objects/
I think this way instead of just answering your question you could understand what's going on,
I think an illustration will be best.
i)
class A
{
int i;
public:
A(int ii) : i(ii) {}
}
The part i(ii) is an example of a member - object initialiser. Since C++ guarantees all constructors of members will be called before the constructor body is entered, this is your only way of specifying which constructor to call for each member.
ii) In C++ there is no super keyword. You must specify the base class as such:
class B : public A
{
public:
B(int i) : A(i) {}
}
That's partially due to the fact C++ allows multiple inheritence.
iii) Note that you haven't created any objects, only pointers to objects. And it's by this method polymorphism via inheritence is acheived in C++.
#include <iostream>
class Base
{
public:
Base(int i)
{}
virtual ~Base() = 0
{}
protected:
int i_;
};
class Derived: public Base
{
public:
Derived(int i, int j) : Base(i), j_(j)
{}
private:
int j_;
};
int main(int argc, char* argv[])
{
//Base b(1); object of abstract class is not allowed
Derived d(1, 2); // this is fine
}
As you can see i_ is being initalized by the Derived class by calling the Base class constructor. The = 0 on the destructor assures that the Base class is pure virtual and therefore we cannot instantiate it (see comment in main).
i) The following is what is known as an initializer list, you can use initializer lists to make sure that the data members have values before the constructor is entered. So in the following example, a has value 10 before you enter the constructor.
Class baseClass
{
int a;
public:
baseClass(int x):a(x)
{
}
}
ii) This is how you would explicitly call a base class constructor from a derived class constructor.
Class derivedClass : public baseClass
{
int a;
public:
derivedClass(int x):baseClass(x)
{
}
}
iii) You can't directly create instances of an abstract class. However, you can create pointers to an abstract base class and have those pointers point to any of its concrete implementations. So if you have an abstract base class Bird and concrete implementations Parrot and Sparrow then Bird* bird could point to either a Parrot or Sparrow instance since they are both birds.
I'm inheriting a class and I would like to call one of its constructors. However, I have to process some stuff (that doesn't require anything of the base class) before calling it. Is there any way I can just call it later instead of calling it on the initializer list? I believe this can be done in Java and C# but I'm not sure about C++.
The data that I need to pass on the constructor can't be reassigned later, so I can't just call a default constructor and initialize it later.
Is there any way I can just call it later instead of calling it on the initializer list?
No, you cannot. The base class constructor must be called in the initializer list, and it must be called first.
In fact, if you omit it there, the compiler will just add the call implicitly.
I believe this can be done in Java and C# but I'm not sure about C++.
Neither C# nor Java allow this either.
What you can do, however, is call a method as an argument of the base class constructor call. This is then processed before the constructor:
class Derived {
public:
Derived() : Base(some_function()) { }
private:
static int some_function() { return 42; }
};
As was said by several people answering, you cannot delay the invocation of a base class constructor, but Konrad has given a good answer that might well solve your problem. However, this does have its drawbacks (for example, when you need to initialize several functions with values whose calculations share intermediate results), so just to be complete, here's another way of solving the problem of fixed initialization order, by using it.
Given the fixed order of initialization, if you have control over the derived class (and how else would you come to fiddle with one of its ctors?), you can sneak in a private base so that it is going to be initialized before the other base, which can then be initialized with the private base's already calculated values:
class my_dirty_little_secret {
// friend class the_class;
public:
my_dirty_little_secret(const std::string& str)
{
// however that calculates x, y, and z from str I wouldn't know
}
int x;
std::string y;
float z;
};
class the_class : private my_dirty_little_secret // must be first, see ctor
, public the_other_base_class {
public:
the_class(const std::string str)
: my_dirty_little_secret(str)
, the_other_base_class(x, y, z)
{
}
// ...
};
The my_dirty_little_secret class is a private base so that users of the_class cannot use it, all of its stuff is private, too, with explicit friendship granting only the_class access to it. However, since it's listed first in the base class list, it will reliably be constructed before the_other_base_class, so whatever it calculates can be used to initialize that.
A nice comment at the base class list hopefully prevents from others breaking things by refactoring.
IMHO I dont think it is possible to defer calling the base class constructor in the way that you mentioned.
Wow, we were all young once. This answer won't work, so don't use it. Content left for historical purposes.
If you have full control over the base class, I'd recommend adding a protected method to do the class initialization, make it virtual, and put the your derived class implementation details in it before it calls its base:
class Base
{
public:
Base()
{
Initialize();
}
protected:
virtual void Initialize()
{
//do initialization;
}
};
class Derived : Base
{
public:
Derived() : Base()
{
}
protected:
virtual void Initialize()
{
//Do my initialization
//call base
Base::Initialize();
}
};
Another option, based on the suggestion from #Konrad is to have a static method to construct the object, e.g.:
class Derived {
public:
Derived(int p1, int p2, int p3) : Base(p1, p2) { }
static Derived* CreateDerived(int p3) { return new Derived(42, 314, p3); }
};
Ive found this useful when extending a class from a library and having multiple parameters to override.
You can even make the constructor private
struct base{
base(int x){}
};
struct derived : base{
derived(int x) : base(x){}
};
This is how base class constructors are invoked in C++ from the initialization list of derived class.