class A
{
public: int a,b,c;
};
class B: public A
{
public: int d;
B():d(0){} // Some hackery needed here
};
int main()
{
B obj;
std::cout<< obj.a << std::endl; // garbage
std::cout<< obj.b << std::endl; // garbage
std::cout<< obj.c << std::endl; // garbage
std::cout<< obj.d << std::endl; // 0
}
How could the subobject data members a,b and c be initialized to 0? I am not permitted to modify class A.
Try
B() : A() , d(0){}
A() value initializes A and since A is a POD the members will be default(zero) initialized
I tested this as I thought it might work (even without Prasoon's answer)
B::B() : A(), d(0)
{
}
might work, because you are then "initialising" A.
It didn't, by the way. Output:
1,32,123595988
This would work though:
// put this in B.cpp anonymous namespace
const A a_init = { 0, 0 ,0 };
followed by:
B::B() : A( a_init), d(0)
{
}
I am testing using g++ 4.3.2. Now THIS worked:
B::B() : A(A()), d(0)
{
}
Perhaps I'm missing something, but how about this?
class B: public A
{
public: int d;
B():d(0){a=b=c=0;}
}
The proper way is of course to have A's constructor initialize it's members. Otherwise, as the members are not private, you can assign them values from inside the B constructor.
a = 0;
etc, actually works.
declare the derived class constructor as shown below
class B: public A
{
public: int d;
B():a(0),b(0),c(0),d(0)
{
}
};
Related
This question already has answers here:
How can I initialize base class member variables in derived class constructor?
(7 answers)
Closed 24 days ago.
#include <iostream>
class A {
public:
const int HP = 200;
A(){
std::cout << this->HP << std::endl;
}
};
class B : public A {
public:
B();
};
Constructing a B object will construct the A potion first.
I expect to reinitialize HP so that B() can print new HP.
Is this feasible for a base class const member ?
I need a member shared between base and child but to be constant in one instance of class, any suggestions?
You can add a constructor to A (and if needed also to B) that accepts the value for the const int member.
Then when you invoke A constructor from B constructor via the initializer list, you can pass this const value to the base.
Code example:
#include <iostream>
class A {
public:
const int HP = 200;
A() {
std::cout << this->HP << std::endl;
}
//----vvvvvv----vvvvvv--
A(int hp) : HP(hp) {
std::cout << this->HP << std::endl;
}
};
class B : public A {
public:
B() {};
//----vvvvvv----vvvvv--
B(int hp) : A(hp) {}
};
int main()
{
B b1;
B b2{ 99 };
}
Output:
200
99
Note: B can also be left as is (without an additional constructor), and pass the required const value to the base.
If I create derived object it calls base constructor first and then derived constructor. Does it mean that parent object also get created when we create derive object?
I don't think parent object gets created, but why does the parent constructor get called?
#include<iostream>
using namespace std;
class A {
public : A(){
cout<<"inside A constructor"<<endl;
}
};
class B : public A{
public : B(){
cout << "inside B constructor" << endl;
}
};
int main() {
B b;
return 0;
}
Output:
inside A constructor
inside B constructor
I don't think parent object get created [...]
You are wrong.
B constists of a A subobject and any members that B has in addition. Consider this example:
struct A {
int a = 0;
};
struct B : A {
B() {}
};
int main() {
B b;
b.a = 42;
}
B inherits the members from A. Those members do not come out of nowhere, but they are part of Bs subobject of type A and that has to be constructed. When you do not call a constructor explicitly then it will be default constructed. The above is roughly equivalent to:
struct A {
int a = 0;
};
struct B : A {
B() : A() {}
// ^^^ call default constructor of A
};
I have a Derived class whose constructor has to populate the fields of a struct that is passed as an argument to the constructor of the Base class. I want to be able to name the fields of the struct that I am populating, to keep my code future-proof (i.e.: resistant to addition and/or reordering of the members of MyStruct).
Note that struct MyStruct has default values, so it cannot be initialised with named fields directly in the initialization list (e.g.: Base({.a = a, .b = b}) does not work). Also, in my case, Base's copy constructor is deleted. Also, I am using C++ 11.
The solution I came up with uses the placement new operator to manually call the constructor of the Base class on the memory pointed to by this. To achieve this I also had to add a protected default constructor to my Base class. Are there any possible downsides to this approach and/or could anyone suggest a better method?
#include <iostream>
struct MyStruct
{
int a = 0;
int b = 1;
};
class Base
{
public:
Base(MyStruct str){
std::cout << "a: " << str.a << ", b: " << str.b << "\n";
}
Base(Base&&) = delete; // no copy constructor
protected:
Base(){ // dummy, does exactly nothing.
// it only exists to be called by
// the derived class's constructor
}
private:
int amember;
};
class Derived : public Base
{
public:
Derived(int a, int b)
{
MyStruct str;
str.a = a;
str.b = b;
new (this) Base(str);
}
private:
int anothermember;
};
int main()
{
MyStruct str;
str.a = 10;
str.b = 20;
Base b(str);
Derived d(10, 20);
return 0;
}
edit: added mention that Base cannot be copied, made explicit that Base::Base() does exactly nothing.
Use a helper function instead like
class Derived : public Base
{
public:
Derived(int a, int b) : Base(make_mystruct(a, b)), anothermember(some_value) {}
private:
int anothermember;
static MyStruct make_mystruct(int a, int b) { return MyStruct(a, b); }
};
I would just like to add that this could be a good opportunity to use IILE, Immediately Invoked Lambda Expression, if you for whatever reason don't want a named helper function:
class Derived : public Base
{
public:
Derived(int a, int b) : Base{[](){
MyStruct str;
str.a = a;
str.b = b;
return str; }()}
{}
};
The benefit is that you will not need to construct the class and it's members only once, since you do everything in the initialization list. If you in the future add non-trivial members to Base, you will be will not have to pay for double initialization.
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
}
Looking for an explanation of some fact in the standard I found this:
An abstract class (10.4) is never a most derived class, thus its
constructors never initialize virtual base classes, therefore the
corresponding mem-initializers may be omitted.
This is from the paragraph 12.6.2 of the final working draft. Since, It's embedded in Note and no example is provided, I don't know how it should be treated. So, I tried the example:
#include <iostream>
struct B{
~B(){}
B(){ std::cout << "B()" << std::endl; }
B(int){ std::cout << "B(int)" << std::endl; }
};
struct A : virtual B
{
int s;
virtual void foo() = 0;
A(int a) : B(a) { std::cout << "A(int)" << std::endl; }
};
struct D : A{
D() : A(10){ }
virtual void foo(){ }
} d;
int main()
{
}
and got the output
B()
A(int)
http://coliru.stacked-crooked.com/a/b16c68226f072ced
in spite of specifying the B's constructor in the ctor-initializer. Is that what they mean?
In this example, D is the most derived class and will construct B using the default (no parameter) constructor.
An abstract class is never most derived because you have to derive from it in order to instantiate it.