Making initialization lists work with inheritance in C++ - c++

The following piece of code gets compiled under g++ 4.6.3 for Linux
#include <iostream>
class A {
public:
int x;
std::string c;
A(int x,std::string c):x(10),c("Hi"){
}
~A(){
std::cout << "Deleting A()" << std::endl;
}
};
class B : public A {
public:
B():A(20,"Hello"){
}
~B(){
std::cout << "Deleting B()" << std::endl;
}
};
int main(){
B o;
std::cout << o.x << std::endl;
std::cout << o.c << std::endl;
return(0);
}
but it does not do what is supposed to do, the type B is not able to change the values of that 2 variables that it inherit from A.
Any explanations about why this doesn't work properly ?

Your base constructor takes those values...and completely disregards them!
Change this:
A(int x,std::string c):x(10),c("Hi"){}
to this:
A(int x,std::string c):x(x),c(c){}

There seems to be some confusion about what you want and how to achieve this.
If I got you right this is what you want:
class A {
public:
int x;
std::string c;
//default initization of A
A():x(10), c("Hi") {}
//initializing the values of A via parameters
A(int x,std::string c):x(x),c(c){}
~A(){
std::cout << "Deleting A()" << std::endl;
}
};
class B : public A {
public:
B():A(20,"Hello"){
}
~B(){
std::cout << "Deleting B()" << std::endl;
}
};
So in this example:
int main()
{
A a;
A a1(2, "foo");
B b;
return 0;
}
a.x == 10, a.c == "Hi"
a1.x == 2, a1.c == "foo"
b.x == 20, b.c == "Hello"

OK, I don't understand what exactly you want and why, but here's a suggestion, with C++11, you can do the following:
struct Base {
int a;
float b;
};
struct Derived: public Base {
Derived(): Base{1,1.0} {}
};
int main() {
Derived d;
}
as long as the base is a POD type.
I'd still prefer A(int x = 10,std::string c = std::string("Hi")):x(x),c(c){...} though.
IMHO, you need to review if you really need that much control over your base class in the first place. You're not really supposed to micro-manage a class from the outside like that, it's an indication of a flaw in your class hierarchy.

Related

collect different types of class and call their methods in c++

Is there any way in C++ to collect different types of classes and call their methods?
What I want to do is as below,
template<namespace T>
class A
{
A method_A1(T a)
{
...
}
void method_A2(int aa)
{
...
}
...
};
class B
{
...
};
class C
{
...
};
class D
{
...
};
A<B> *b;
A<C> *c;
A<D> *d;
b -> method_A2(3);
c -> method_A2(5);
In this code object b,c,d they are totally different object, right? Not related.
But I want to bind them with a array, so...
z[0] = b;
z[1] = c;
z[2] = d;
like this.
I found some solutions, however the solutions are only for collecting different types. (using void* arrays or vectors for inherited objects) I also wanna access to their methods.
z[0] -> method_A2(3);
z[1] -> method_A3(5);
like this.
In this case how should I do?
Thanks in advance.
typedef boost::variant<A<B>, A<C>, A<D>> AVariant;
std::array<AVariant, 3> z;
z[0] = *b;
z[1] = *c;
z[2] = *d;
Then you can inspect each element's type if needed, or "visit" them using boost::static_visitor as shown here: http://www.boost.org/doc/libs/release/doc/html/variant.html
Why you don't use inheritance and polymorphisms. I have posted an example of what exactly can be a solution of your problem. See the main function:
#include <iostream>
class weapon {
public:
int fireRate;
int bulletDamage;
int range;
int activeBullet;
public:
virtual void fire(void) {std::cout << "machine " << '\n';}
virtual ~weapon() {std::cout << "destructor is virtual" << '\n';}
};
class machineGun: public weapon {
public:
void fire(void) {std::cout << "machine gun firing" << '\n';}
~machineGun(void) { std::cout << "machine gun destroyed" << '\n';}
};
class flamer: public weapon {
public:
void fire(void) {std::cout << "flamer firing" << '\n';}
~flamer(void) {std::cout << "flamer destroyed" << '\n';}
};
int main(void)
{
const int count = 2;
weapon *weapons[count];
machineGun *a = new machineGun();
flamer *b = new flamer();
weapons[0] = a;
weapons[1] = b;
weapons[0]->fire();
weapons[1]->fire();
delete a;
delete b;
}
If you don't want to change your classes' hierarchy, you can try having an array of callable objects. Something like:
#include <iostream>
#include <functional>
#include <array>
class A
{
public:
void Foo(int a)
{
std::cout << "Foo " << a << std::endl;
}
};
class B
{
public:
void Bar(int a)
{
std::cout << "Bar " << a << std::endl;
}
};
int main()
{
using namespace std::placeholders;
A a;
B b;
auto a_func = std::bind(&A::Foo, a, _1);
auto b_func = std::bind(&B::Bar, b, _1);
std::array<std::function<void(int)>, 2> arr = {
std::bind(&A::Foo, a, _1),
std::bind(&B::Bar, b, _1)
};
arr[0](1);
arr[1](2);
return 0;
}
BTW, this will only work if you use compiler with full C++11 support.

C++ passing array of pointers to function

I have problem with passing array of pointers to a function.
Class CTree01 is child of CDecorationObj.
When I use for loop, it's working fine.
Here's my code:
CTree01 *trees01;
int numTree01 = ...;
trees01 = new CTree01[numTree01];
//main loop
for(int i=0;i<numTree01;i++)
{
{
//Everything is working okay here, renders all trees
glPushMatrix();
trees01[i].DrawOnTerrain(camera);
glPopMatrix();
}
}
but since i replaced for with a function, it's not working anymore:
void DrawDecorationType(CDecorationObj* objs, int number, CCamera *camera)
{
int x,z;
for(int i=0;i<number;i++)
{
{
glPushMatrix();
objs[i].DrawOnTerrain(camera);
glPopMatrix();
}
}
}
//main loop
DrawDecoration(trees01, numTree01, camera);
When I do in that function:
objs[0].DrawOnTerrain(camera);
it works, and it crashes only when I render objects with index > 0 so I think it must be problem with parameter passed to the function.
Let me see if I can explain the problem using couple of simple classes.
Let's say you have:
struct Foo
{
char a;
};
struct Bar : Foo
{
char b;
};
sizeof(Foo) is 1 and sizeof(Bar) is 2.
And you create an array of Bar object using:
Bar* barPtr = new Bar[2];
The layout of memory that barPtr points to looks like:
Bar(0) Bar(1)
| |
v v
+---+---+---+---+
| a | b | a | b |
+---+---+---+---+
If you pass that pointer to a function a Foo*, that function will interpret the memory as (since sizeof(Foo) == 1):
Foo(0)
| Foo(1)
| |
v v
+---+---+
| a | a |
+---+---+
As you can see, Foo(1) is not really a Foo object. It is really the Bar sub-object of Bar(0). This can easily lead to undefined behavior. Depending on the kinds of data a base class and a derived class have, it could easily crash your program.
The key point is that a pointer that points to an array of derived class objects cannot be treated as a pointer that points to an array of base class objects.
Very good explanation from R Sahu. It clearly describes why your code isn't working and deserves to be accepted.
So what can you do instead?
As far as I understand you want to pass all your CTree01 to a function in one call and have that function iterate all your CTree01s.
The only way I know is to make the container (i.e. array, vector) holding the base class pointers instead of CTree01.
Something like this:
class A
{
public:
A() { cout << "A constructor" << endl;}
virtual ~A() { cout << "A destructor" << endl;}
void hello() { cout << "Hello from A" << endl;}
};
class B : public A
{
public:
B() { cout << "B constructor" << endl;}
~B() override { cout << "B destructor" << endl;}
};
void f(array<A*,2>& t)
{
for(auto e : t)
{
e->hello();
}
}
int main()
{
array<A*,2> z; // Base class pointer array
z[0]=new B; // but it can still hold pointers to B
z[1]=new B;
f(z);
delete z[0];
delete z[1];
return 0;
}
or using vector instead of array
class A
{
public:
A() { cout << "A constructor" << endl;}
virtual ~A() { cout << "A destructor" << endl;}
void hello() { cout << "Hello from A" << endl;}
};
class B : public A
{
public:
B() { cout << "B constructor" << endl;}
~B() override { cout << "B destructor" << endl;}
};
void f(vector<A*>& t)
{
for(auto e : t)
{
e->hello();
}
}
int main()
{
vector<A*> z;
z.push_back(new B);
z.push_back(new B);
f(z);
delete z[0];
delete z[1];
return 0;
}

How to iterate over base objects that is a certain derived class

Lets say I have implemented the following classes
class A
{
public:
virtual void printA()
{
cout << "Hi from A!" << endl;
}
};
class B : public A
{
public:
virtual void printB()
{
cout << "Hi from B!" << endl;
}
};
class C : public B
{
public:
void printC()
{
cout << "Hi from C!" << endl;
}
};
Lets also say I have created a std::vector<A *> vec that contains random amount of objects instantiated from A, B, and C. Now lets say I am forced to iterate through all the objects in vec but only call objects that have the printC() method (i.e C instances). What is the best way to do this?
int main()
{
std::vector<A *> vec;
....
// insert random objects from both A, B and C into vec
....
for(vector<A *>::iterator x = vec.begin();
x != vec.end();
x++)
{
if(dynamic_cast<C *>(*x) != 0) // 1. is this OK?
(*x)->printC();
else
(*x)->printA(); // 2. is this also OK?
}
}
Is 1 Ok? And if so is this the best practice?
Also will 2 cause problems in the case of C instances?
Maybe these are stupid questions, but Im quite new to C++ and how polymorphism works in C++ is very strange to me. Thanks
I think you mean the following
#include <iostream>
#include <vector>
int main()
{
class A
{
public:
virtual ~A() = default;
virtual void print() const
{
std::cout << "Hi from A!" << std::endl;
}
};
class B : public A
{
public:
void print() const
{
std::cout << "Hi from B!" << std::endl;
}
};
class C : public B
{
public:
void print() const
{
std::cout << "Hi from C!" << std::endl;
}
};
std::vector<A *> v = { new A(), new B(), new C() };
for ( A *p : v ) p->print();
return 0;
}
The output is
Hi from A!
Hi from B!
Hi from C!
1 won't work, since *x has type A*, and A doesn't have a printC member. It should be:
if (C * c = dynamic_cast<C *>(*x)) {
c->printC();
}
2 is fine, but doesn't match your description; you say you want to "only call objects that have the printC() method", while this calls printA() on the other objects.
This does seem like an odd design though; you'd usually define a single virtual function, implemented by each class to do the right thing for that class, then call that unconditionally for everything.

How to do I/O on a pointer to a base class?

For example, I have a base class A and its derived classes B, C, and so on. I have data with a pointer pointing to A. It might be new B, new C, and so on. Any easy way to write and read the pointer to/from a stream? My question is on how to get to know the concrete type. An example to show what I mean.
struct A { int i; };
struct B : public A { char c; };
struct C : public A { float f; }
struct Data
{
unique_ptr<A> mA;
};
Data data;
User works on data and then write out to a file and read in from the file.
The answer is you don't, you use virtual functions.
#include <iostream>
struct A {
int i;
virtual void describe() {
std::cout << "A:" << i << std::endl;
}
};
struct B : public A {
char c;
virtual void describe() override {
// Assume a 'B' wants to also output the A stuff.
std::cout << "B:" << c << ":";
A::describe();
}
};
struct C : public B {
float f;
virtual void describe() override {
// Assume a 'C' wants to also output the B stuff and A stuff.
std::cout << "C:" << f << ":";
B::describe();
}
};
#include <vector>
int main() {
std::vector<A*> bar;
A a;
a.i = 10;
B b;
b.i = 22;
b.c = 'b';
C c;
c.i = 5;
c.c = 'X';
c.f = 123.456;
bar.push_back(&a);
bar.push_back(&b);
bar.push_back(&c);
for (size_t i = 0; i < bar.size(); ++i) {
bar[i]->describe();
}
}
http://ideone.com/12BEce

In what order do C++ objects passed as arguments to constructors of other objects go out of scope?

When I compile the following code with g++, the object of class A seems not to be destructed when the object of class C is constructed, and the B.ref_a reference is not broken when accessed by the constructor of object of class C:
#include <iostream>
struct A
{
A(int aa)
{
a = aa;
}
~A()
{
std::cout << "A out" << std::endl;
}
int a;
};
struct B
{
B(const A& a)
: ref_a(a)
{
}
~B()
{
std::cout << "B out" << std::endl;
}
const A& ref_a;
};
struct C
{
C(const B& b)
{
c = b.ref_a.a + 1;
}
int c;
};
int main(void)
{
C c(B(A(1)));
std::cout << c.c << std::endl;
}
However, is it guaranteed by the C++ language?
Here, the temporary objects go out of scope when the instruction has finished its execution. That is, just after the constructor of C has returned.
And yes, this is guaranteed by the C++ standard.