class base
{
private:
int a;
};
class base2
{
private:
int b;
};
class derived:public base,public base2
{
private:
int c;
};
main()
{
base b;
derived d;
cout<<size of(base)<<size of(base2)<<size of(derived);
}
since int a and int b are private variables.so they are not getting inherited in derived class.so the output should be 4 4 4 but it is
output:4 4 12
why?
since int a and int b are private variables.so they are not getting inherited in derived class
That's wrong - of course they are getting inherited, the code in the base class wouldn't be able to work without them. It's just that derived cannot get to them, but it does not change the sizeof the derived class.
Consider this extension of your example:
class base {
private:
int a;
protected:
base() : a(123) {}
void showA() {cout << a << endl;}
};
class base2 {
private:
int b;
protected:
base2() : b(321) {}
void showB() {cout << b << endl;}
};
class derived:public base,public base2 {
private:
int c;
public:
derived() : c (987) {}
void show() {
showA();
showB();
cout << c << endl;
}
};
Even though your derived class cannot read or change a and b, it can show their values by calling the corresponding functions in its bases. Therefore, the variables must remain there, otherwise the showA and showB member functions wouldn't be able to do their work.
private: or protected: or public: annotations on member fields affect only visibility. But the fields are still in the classes.
Take several days to read a good C++ programming book.
Related
Consider the following code
class A {
int x, y;
public:
A(){}
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
int a, b, c;
public:
B(){}
};
int main() {
A obja;
B objb;
obja.PrintSize();
objb.PrintSize();
}
The intent of "PrintSize()" is to get the size of the current class where we are calling it from. What happens is that this-keyword refers to class A even though we are calling it from B. We don't want this since we need this function to be general for child classes.
We could obviously redefine the function verbatim to every class. The code would become harder to hande since there's so many unnesessary lines. Not to mention that re-writing the function to every class would defeat the purpose of deriving it in the first place.
Here's my temporary fix:
class A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class C : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class D : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
While the accepted answer may have solved the immediate problem, you suddenly have no common base class for B and C. They inherit from two unrelated classes, namely A<B> and A<C>.
An alternative is to create a common base that defines an interface (called Interface below) and to add the CRTP class template between the derived classes and the interface. This lets you keep pointers and references to Interface and call the virtual member functions using those.
Here's an example of storing pointers to the common base class in a vector:
#include <iostream>
#include <memory>
#include <vector>
struct Interface {
virtual ~Interface() = default;
virtual void PrintSize() const = 0;
virtual void do_stuff() const = 0;
};
template<typename T>
struct Printer : public Interface {
void PrintSize() const override {
std::cout << sizeof(T) << '\n';
}
};
class B : public Printer<B> {
int a{};
public:
void do_stuff() const override { std::cout << "B doing stuff\n"; }
};
class C : public Printer<C> {
int a{}, b{}, c{};
public:
void do_stuff() const override { std::cout << "C doing stuff\n"; }
};
int main() {
std::vector<std::unique_ptr<Interface>> objs;
objs.emplace_back(std::make_unique<B>());
objs.emplace_back(std::make_unique<C>());
for(auto& ptr : objs) {
ptr->do_stuff();
ptr->PrintSize();
}
}
Possible output:
B doing stuff
16
C doing stuff
24
You can use the CRTP idiom to do this.
https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c
The idea is the parent class is a template, so you can have access to the type of the child class directly in it.
With that, you'll be able to remove all "PrintSize" from child class.
Example :
template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};
class B : public A<B> {
int a, b, c;
public:
B() {}
};
class C : public A<C> {
public:
C() {}
};
int main() {
C objc;
B objb;
objc.PrintSize();
objb.PrintSize();
}
The output is :
8
20
I try to do something like this:
class A{
public:
A(){number = 1;}
int number;
};
class B : public A{
public:
B(){number = 2;}
};
class Base {
public:
Base() {myAttribute = new A();}
int returnAttrNumber(){return myAttribute->number;}
A *myAttribute;
};
class Inherited : public Base{
public:
Inherited(){myAttribute = new B();}
B *myAttribute;
};
int main()
{
Inherited *i = new Inherited();
std::cout << i->returnAttrNumber(); // outputs 1, because it gets the A not the B. I want it to output 2, to get the B object in returnAttrNumber()
}
So, class Base holds an object A. Inherited holds an A-derived object B. And I try to call a method on the base class, but I want it to cast down in the hirarchy of the corresponding Object as far as possible (without static_cast or dynamic_cast) and then take the B object, not A and do stuff (returning it's number in in this case)
Is there a way to do that downcasting from a base class in C++ without big difficulties?
Thanks for answers!
This is very bad design. The quick answer is you can access variable from the base class via the fully qualified identifier. Take the following example:
#include <iostream>
class A
{
public:
A()
: var(1) {}
protected:
int var;
};
class B : public A
{
public:
B()
: var(2) {}
int getBVar() const
{
return var;
}
int getAVar() const
{
return A::var;
}
private:
int var;
};
int main()
{
B b;
std::cout << "A: " << b.getAVar() << std::endl;
std::cout << "B: " << b.getBVar() << std::endl;
}
Which outputs the following:
A: 1
B: 2
About the down casting bit... Base and Inherited have different variables. You can not safely case one to the other.
Well as rioki said,
Base and Inherited have different variables
This is because I redeclared MyAttribute as a B in Inherited. This was the mistake. I thought, when I declare it with the same name, it will be the same variable, that's wrong.
So the whole solution for this is to uncomment this one line in Inherited. Working code:
class A{
public:
A(){number = 1;}
int number;
};
class B : public A{
public:
B(){number = 2;}
};
class Base {
public:
Base() {myAttribute = new A();}
int returnAttrNumber(){return myAttribute->number;}
A *myAttribute;
};
class Inherited : public Base{
public:
Inherited(){myAttribute = new B();}
//B *myAttribute;
};
int main()
{
Base *i = new Inherited(); // this works, what is necessary in my case
std::cout << i->returnAttrNumber(); // outputs 2 now
}
For my C++ program I have a lot of classes where a member should be of one of two types which have the same base class.
I thought I could implement this with pointers but I don't get it to work.
Example: lets assume we have a class A with a member b_ of class B:
class A{
public:
A(B b): b_{b} {}
private:
B b_;
}
The class B has only one function which is pure virtual:
class B{
public:
virtual void print() = 0;
}
now I have two derived classes of B and I want to change A in a way, that it could hold eihther objects of class B1 or B2:
class B1: public B{
public:
void print(){cout << "B1\n";}
}
class B2: public B{
public:
void print(){cout << "B2\n";}
}
My plan was to use unique pointers:
class A{
public:
A(std::unique_ptr<B> b): b_{std::move(b)} {}
private:
std::unique_ptr<B> b_;
}
int main(){
std::unique_ptr<B> b;
if (some condition){
b = make_unique<B1>(new B1()) ///?
}else{
b = make_unique<B2>(new B2()) ///?
}
A(b);
A.getB()->print();
}
There are several mistakes on your code. First of, you can't have two definitions of A. Second, you must pass the unique_ptr as r-value reference (std::move) since it is not copyable. Last, make a variable of type A (a) and then call methods on it.
#include <memory>
#include <iostream>
using namespace std;
class B{
public:
virtual void print() = 0;
virtual ~B() {};
};
class B1: public B{
public:
void print(){cout << "B1\n";}
};
class B2: public B{
public:
void print(){cout << "B2\n";}
};
class A{
public:
A(std::unique_ptr<B> b): b_{std::move(b)} {}
auto *getB() { return b_.get(); }
private:
std::unique_ptr<B> b_;
};
int main()
{
std::unique_ptr<B> b;
if(false)
b = make_unique<B1>();
else
b = make_unique<B2>();
A a(std::move(b));
a.getB()->print();
}
I have written a C++ program.
#include <iostream>
#include <string>
using namespace std;
class A
{
int a;
public:
void read()
{
cin>>a;
}
};
class B:public A
{
public:
B()
{ }
};
class C:public A
{
public:
C()
{}
};
class D:public B,public C
{
public:
void display()
{
cout<<a<<endl;
}
};
void main()
{
A a1;B b1;C c1;
D d1;
d1.display();
}
I get a message saying there is ambiguity. B is inheriting A.. So B class would inherit item 'a' from class A. Also, C class will inherit item 'a' from class A. Now if im trying to inherit both B and C classes in class D, which item 'a' will i be able to access ?? from class B or from class C ?? Is there any way where i can remove the ambiguity .?
You can fix your ambiguity problem by using one of the following options:
Be explicit about the base class
Use B as the explicit base class
void display()
{
cout<< B::a <<endl;
}
or use C as the explicit base class.
void display()
{
cout<< C::a <<endl;
}
Use virtual inheritance
Change B and C to use virtual inheritance.
class B: virtual public A
{
public:
B() {}
};
class C: virtual public A
{
public:
C() {}
};
This is a code fro diamond tree problem of multiple inheritance
and according to me this code is cool but it is showing some error on compilation
..help me to figure the error
#include<iostream>
using namespace std;
class A //A Diamond tree problem
{
int x;
public:
A(int i) { x = i; }
void print() { cout << x; }
};
class B: virtual public A
{
public:
B():A(10) { }
};
class C: virtual public A
{
public:
C():A(20) { }
};
class D: public B, public C{
};
int main()
{
D d;
d.print();
return 0;
}
It would be useful to see the error:
In constructor ‘D::D()’:
error: no matching function for call to ‘A::A()’
When using virtual inheritance, the virtual base class must be initialised by the most derived class. In this case, that is D; so in order to be able to instantiate D, it must initialise A:
class D: public B, public C
{
public:
D():A(42) {}
};
Alternatively, you could provide A with a default constructor. Declaring any constructor will prevent the compiler from implicitly generating one for you.
You need to provide default construct for D and call A in member initialize list:
class D: public B, public C{
public:
D():A(30){}
};
Or you could provide a default A constructor
A():x(0) {}