Problem with derived class in c++ with no data member - c++

I'm learning c++ inheritance and facing problems with the following exercise to create a base class A and a derived class B with certain requirements. I have my answer written down below, but there seems to be some problems with it. I also have a few question at the end of this post.
class A {
private:
int x;
protected:
A (): x(0) { }
A (int n): x(n) { }
int get() const {return x;}
public:
virtual void foo() = 0;
};
class B : public A {
public:
B (): { A(); }
B (int n): { A(n); }
virtual void foo() { std::cout << get();}
};
My questions are:
I'm pretty sure my code is not correctly written, but can anyone tell me what's incorrect?
Since x is private in A, B wouldn't be able to inherit that data member. So how is B able to invoke the constructor?
I'm pretty sure that A is an abstract class, but is B an abstract class too?

It's almost okay, there's two thing that is wrong:
First you have an empty constructor initializer list in the B constructors. That will lead to build errors.
Then in the B constructor the statement A() creates a temporary A object, which is promptly discarded and destructed. You need to "call" the parent class constructor from the B constructor initializer list:
B() : A() { /* Empty */ }
You meed to do the same for the parameterized B constructor as well.
You can't access private members in the base-class, but protected is okay. That's now protected works with public inheritance: The child class can access the base class protected members.
Since you override foo with an implementation B is not abstract, there's no abstract members of B.

Related

Can't access protected member variables of the most base class through std::unique_ptr in diamond

I am not an advanced programmer. Suppose there is a classic diamond inheritance:
class Base
class A: virtual public Base
class B: virtual public Base
class Last: public A, public B
Suppose Base has a variable, m_x, that is common to both A and B, such that only one of A, or B, can be called at a time, not both (which is what is needed). To get around this, this is used:
class Last: public A, public B
{
private:
std::unique_ptr<Base> m_p;
public:
Last(int i)
{
if (i)
m_p = std::unique_ptr<Base>(new A());
else
m_p = std::unique_ptr<Base>(new B());
}
};
This is fine, but now m_p->m_x cannot be accessed anymore because it says it's protected, but both A and B call m_x in their constructors directly, with no problems.
Is this a known limitation or is this the wrong way to do it? If it's wrong, what solutions are there?
Here is some code based on the diagram found here (a bit lower on the page):
#include <iostream>
#include <memory>
class Power
{
protected:
double m_x;
public:
Power() {}
Power(double x): m_x {x} {}
virtual ~Power() = default;
};
class Scanner: virtual public Power
{
public:
Scanner() {}
Scanner(double x): Power(x) {} // scan document
};
class Printer: virtual public Power
{
public:
Printer() {}
Printer(double x): Power(x) {} // print document
};
class Copier: public Scanner, public Printer
{
private:
std::unique_ptr<Power> m_p;
public:
Copier() {}
Copier(double x, int i)
{
if (i)
m_p = std::unique_ptr<Power>(new Scanner(x));
else
m_p = std::unique_ptr<Power>(new Printer(x));
}
void print() { std::cout << this->Power::m_x << '\n'; }
};
int main(int argc, char *argv[])
{
Copier *copier {new Copier(1.618, 0)};
copier->print();
copier = new Copier(3.14, 1);
copier->print();
return 0;
}
Using both this->m_p and this->Power::m_x (according to answers and comments) compiles, but the output is 0.
To be sure I spell it out all: not only I am quite a beginner, but, given the example above, it oesn't really have to stay that way if there is another alternative to call Scanner or Printer only one at a time from inside Copier. I am not asking for opinions, I understand it's forbidden, but I won't reject them coming from more experienced users. After all, I am learning.
Both virtual inheritance and std::unique_ptr are red herrings. The problem comes down to this:
class Base
{
protected:
int m_x;
};
class Last : public Base
{
public:
Last()
{
Base base;
base.m_x = 0; // error
m_x = 1; // no error
}
};
The error is something like error C2248: 'Base::m_x': cannot access protected member declared in class 'Base' or error: 'int Base::m_x' is protected within this context.
The explanation is that protected is a somewhat special case. It does not only work on class level but also on the object level. And you have two relevant objects here:
The Last object which is being created by the constructor, i.e. the one pointed to by this. It's also a Base object because of the is-a inheritance relationship.
The local object named base within the constructor.
Now, the problem is that in the line base.m_x = 0;, you are in the context of the first object and not the second one. In other words, you are trying to access the m_x of base from outside base. C++ simply does not allow this.
A very technical explanation can be found in the C++ standard at ยง11.4 [class.protected], a more easily understandable one in an excellent answer here on Stack Overflow.
protected doesn't mean quite what you think it does.
Although Last is derived from Base, member functions of Last don't have access to the protected members of any Base object - just those Base objects that are sub-objects of some Last object.
So you can write: this->Base::x because *this is a Last object, but not m_p->x, because *m_p is of static type Base.
As others have noted, I think this is actually an XY problem. Having an object which derives from two classes, and then also has a pointer to another object of one of those classes is very strange indeed. I think you need to clarify what you are trying to do.

OOPS Memory Allocation for Base class under Inheritance?

Program:
class A
{
int a;
public:
void geta()
{
a=10;
}
void puta()
{
cout<<"a : "<<a;
}
};
class B : public A
{
int b;
public:
void getb()
{
geta(); b=20;
}
void putb()
{
puta(); cout<<"b : "<<b;
}
};
int main()
{
B ABC;
ABC.getb();
ABC.putb();
return 0;
}
The Problem:
The above program allocates memory for derived class object & calls its relevant methods.
The base class is inherited as public, and as the variable 'a' is a private member, it will not get inherited.
So, the program should not allocate memory for this variable.
But, when the above is executed, 'a' variable will be allocated even though it is not inherited.
Could anyone help me understand this?
Thank You.
as the variable 'a' is a private member, it will not get inherited. So, the program should not allocate memory for this variable.
Your assumption is mistaken. Public inheritance models an "is-a" relationship. That is, class Derived is-a Base. Anything you can do with a Base, you should be able to do with a Derived. In order for this to be true, it necessarily must contain everything that Base contains.
In your example, it's perfectly legal to say:
B b;
b.put_a();
that is, to use A methods on B object. This would not work if the a member was absent.
The base class is inherited as public, and as the variable 'a' is a private member, it will not get inherited.
When a base class member is declared as private it doesn't mean it does not get inherited. It just means that the member variable will be inherited (will be part of the derived class) but won't be accessible.
For example, in:
class A {
private:
int a;
int b;
// ...
};
class B : public A {};
auto main() -> int {
B b;
}
When we allocate B b; we are allocating both a and b member objects of the class A.
The variable a is inherited, though you have no access to it. For example, the following code would work:
class A {
private:
int x;
public:
int getXfromA() { return x; }
};
class B : public A {
public:
int getXfromB() { return getXfromA(); }
};
However, x cannot be directly accessed from B class here.
You're confusing storage with access control.
If object B inherits from object A, it has all of object A's methods and members, even if it cannot access them directly.
The purpose of private and protected is access control. If you mark members and methods as private, then nothing outside can access those methods and members. But, those things are part of the object nonetheless.
This allows you to implement class invariants without exposing the details, including classes that inherit from the base.
Here's an example that encapsulates capturing the creation time of an object in the base class:
#include <time.h>
#include <iostream>
class Base
{
private:
time_t create_time;
public:
Base()
{
create_time = time(0);
}
time_t get_create_time() { return create_time; }
};
class Derived : public Base
{
public:
Derived() { }
};
int main()
{
Derived D;
std::cout << D.get_create_time() << std::endl;
}
Derived doesn't know or need to know how the creation time was captured. It's a class invariant it inherited by deriving from Base.
This is a pretty simple example, but you could imagine more complex examples.

Why private members get inherited?

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.

Inheritance - C++

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.

C++: newbie initializer list question

Newbie here. I am looking at company code.
It appears that there are NO member variables in class A yet in A's constructor it initializes an object B even though class A does not contain any member variable of type B (or any member variable at all!).
I guess I don't understand it enough to even ask a question...so what's going on here!? My intuition is that you need a variable before you even try to initialize it. How is it possible (or what good does it do) to initialize an object without having the object?
.h:
class A: public B
{
public:
A(bool r = true);
virtual ~A;
private:
}
.cpp:
A::A(bool r) : B(r ? B::someEnumeration : B::anotherEnumeration)
{
}
A::~A()
{
}
Please help.
Thanks,
jbu
Class A (publicly) inherits from class B:
class A: public B
The only way to initialize a base class with parameters is through the initializer list.
This is actually the only way to call the ctor of a base class in C++ as there is noch such thing as super().
class A : public B
{
};
class B
{
public:
int x;
};
A is a derived type from B. Or A inherits B.
So this is valid...
A a;
a.x = 3;
The rest of your code is just calling B's constructor when A is constructed.
class A: public B
{
public:
A(bool r = true); // defaults parameter 1 as "true" if no arguments provided ex A *pA = new A();
virtual ~A;
private:
}
.cpp
A::A(bool r) : B(r ? B::someEnumeration : B::anotherEnumeration)
{
// calls parent class, and initialize argument 1 with some enumeration based on whether r is true or false
}
A::~A()
{
}
Since construtor cannot be inherited so base class data members are to be initialized by passying argument in derived class constructor and with the help of initialization list.
You should also know that in case of polymorphic class initialization of vptr to respective virtual table is done only in constructor.