Probably an easy question for someone out there, but what am I doing wrong in the below example? I'm trying to build a global class which contains instantiations of other classes within... I think where I'm going wrong boils down to the below example. Getting a seg fault, as if *b is never created. Thanks in advance!!
#include <iostream>
using namespace std;
class A;
class B;
class B
{
public:
B()
{
b = 99;
}
~B();
int Getb() {return b; }
void Setb (int x) { b = x; }
private:
int b;
};
class A
{
public:
A()
{
B *b = new B;
}
~A();
B * b;
void Printout()
{
cout<<b->Getb()<<endl;
}
private:
};
int main()
{
A *a = new A;
a->Printout();
cin.get();
}
A() {
B *b = new B;
}
B * b;
In the constructor you're declaring a new local variable that gets assigned the address of the freshly allocated B, and then forgotten!
The instance field b is never assigned to because it is shadowed by the local variable of the same name in the constructor.
You probably mean to do
A() {
b = new B;
}
A()
{
B *b = new B;
}
should be
A()
{
b = new B;
}
In your version there a variable called b in the A constructor. This variable hides the A class member also called b (which was obviously the one you wanted to use).
In the cosntructor A::A() you don't initilize the A::b member, but a local variable instead. Try doing:
A() {
b = new B;
}
or better:
A():b(new B) {}
And even better, don't use the raw pointer at all.
B *b = new B;
Creates a local variable named b which shadows the class member b. You need to initialize the class member, and you should do it in an initialization list.
A() : b(new B) {}
Your next step is to fix the memory leak caused by never calling delete on the pointers you dynamically allocate, but since this is a learning exercise it's probably not terribly important (yet).
Although quite a few people have pointed out one way of fixing the problem you're seeing, none seems (to me, anyway) to be giving advice about how to really make the code better.
Your definition of B is what's called a quasi-class. To make a long story short, your B can be simplified a lot without losing anything:
struct B {
int b;
B() : b(99) {}
};
Everything else you've done (get/set, destructor) are accomplishing absolutely nothing. Your A class not only accomplishes just about as little, but does it even more poorly. Others have already pointed out the problem with A's constructor defining a local B object, and then leaking that object. None (that I've seen yet, anyway) has pointed out that even when you fix that, your definition of A will leak the B object anyway, because even though it creates a B object as part of creating an A object, it does not destroy the B object when the A object that contains it is destroyed.
I don't see any reason for your A class to dynamically allocate the B object at all (or, when you get down to it, to even exist). I'd define A more like this:
class A {
B b;
public:
void print() { std::cout << b.b << "\n";
};
It would be better, however, if a B object knew how to insert itself into a stream -- and if it used the normal syntax for that as well:
std::ostream &operator<<(std::ostream &os, B const &b) {
return os << b.b;
}
With this in place, your A class adds nothing at all, so your entire program becomes something like this:
struct B {
int b;
B() : b(99) {}
};
std::ostream &operator<<(std::ostream &os, B const &b) {
return os << b.b;
}
int main() {
std::cout << B() << "\n";
return 0;
}
Great tips guys, even though in retrospect I obfuscated my issue with naming the int variable b (should've been anything but b!!). That said, you guys "pointed" me in the direction to initialization lists, destructors, and ultimately to the topic of composition. Many thanks How to implement class composition in C++?
Related
Look at following code:
class A
{
protected:
int aa = 1;
};
class B : public A
{
private:
int bb = 2;
public:
int getbb() { return bb; }
};
class C : public A
{
private:
int cc = 3;
public:
int getcc() { return cc; }
};
int main()
{
std::vector<A> a;
B b;
C c;
a.push_back(b);
a.push_back(c);
a[0].getbb(); //getbb() unaccessible;
a[1].getcc(); //getcc() unaccessible;
}
A is the based class. B and C is the derived classes. I want to set a vector to hold either B or C, and use vector a to hold A. However, since a is a vector containing A's objects, I can't access methods in B and C. Is there anyway to make a[0].getbb() and a[1].getcc() work?
Your vector of A is not capable of holding Bs or Cs, because it stores A by value, resulting in object slicing when B or C is stored. In particular, this means that when you store B, only aa gets stored; bb gets sliced away.
In order to store subclasses without slicing use a container of pointers - preferably, of smart pointers.
This wouldn't help you access functionality specific to B or C without a cast. One way to solve this problem is to give virtual member functions for B's and C's functionality to A, and make calls through A-typed reference of B or C.
Not without invoking undefined behaviour.
The problem is that a.push_back(b) and a.push_back(c) do not append objects b and c to the vector. They create instances of A that hold only the "A parts". This is called object slicing.
So there is no object of type B and no object of type C in the vector.
You force the issue and make your code compile by doing something like
static_cast<B &>(a[0]).getbb();
but this just has undefined behaviour, since it treats a[0] as being of type B when it is really of type A. Which makes it a really bad idea. Although it will (probably) compile, it could do anything - and probably not what you expect.
If your vector contains A * rather than A it is possible. For example;
int main()
{
std::vector<A *> a;
a.push_back(new B);
a.push_back(new C);
B* b = dynamic_cast<B *>(a[0]);
if (b) // if a[0] actually points at a B ....
b->getbb();
else
complain_bitterly();
C *c = dynamic_cast<C *>(a[1]);
if (c)
c->getcc();
else
complain_bitterly();
}
Of course, doing this has practical trap doors as well - such as requiring class A having at least one virtual member. It would be better off to work with a polymorphic base, and override virtual functions.
In other words, your design is broken, so fix it so it doesn't somehow require you to morph an object to a different type.
An alternative to using pointers is to use a vector of std::reference_wrappers and polymorphic classes. Small example below:
#include <functional> // for std::reference_wrapper
#include <iostream>
#include <vector>
class A
{
public:
virtual void printme()
{
std::cout << "A" << std::endl;
}
virtual ~A() = default;
};
class B: public A
{
public:
void printme() override
{
std::cout << "B" << std::endl;
}
};
class C: public A
{
public:
void printme() override
{
std::cout << "C" << std::endl;
}
};
int main()
{
std::vector<std::reference_wrapper<A>> a;
B b;
C c;
a.emplace_back(b);
a.emplace_back(c);
a[0].get().printme(); // need to "get()" the raw reference
a[1].get().printme();
}
Live on Coliru
According the the cpp reference, there seems to be a way to achieve this by using dynamic_cast. You first need to make your vector a vector of pointers to the base class A. Then when accessing any element, you can check if it is a B* (or a C*) by checking the result of the dynamic_cast operator.
From the CPP reference:
dynamic_cast < new_type > ( expression )
... If the cast is successful, dynamic_cast returns a value of type new_type. If the cast fails and new_type is a pointer type, it returns a null pointer of that type...
Accordingly, you can do this:
std::vector<A*> a;
B b;
C c;
a.push_back(&b);
a.push_back(&c);
...
int i = something;
B* pB = dynamic_cast<B*>(a[i]); if(pB != nullptr) pb->getbb();
C* pC = dynamic_cast<C*>(a[i]); if(pC != nullptr) pC->getcc();
p.s: It is highly questionable as design approach though. The recommended OOP approach would be certainly to use a virtual method in the base class A and override it in B and C. But (hopefully) this answers the exact question as stated in the title.
If you're sure they're instances of B and C, use cast:
static_cast<B>(a[0]).getbb();
static_cast<C>(a[1]).getcc();
OK, you may also create a vector of A*:
std::vector<A*> as;
as.push_back(new B);
as.push_back(new C);
B* b = (B*) as[0];
b->getbb();
c->getcc();
Now you only have to remember about freeing objects with delete.
You may use "Type IDs":
class A {
// ...
virtual int getTypeID() { return 0; }
}
class B {
// ...
virtual int getTypeID() { return 1; }
}
// analogically for C
It's virtual but is in prototype of A
Now use:
switch(a.getTypeID()) {
case 0:
// It's normal A
break;
case 1:
// It's B
// ...
break;
case 2:
// It's C
// ...
break;
}
First, sorry for thw poor title... I don't really know how to express with one
sentance what I mean... You are weclome to edit the title.
I have three classes A, B and C.
class A{
public:
A(double a):a_(a){}
private:
double a_;
}
class B{
public
B():a_ptr_(NULL){}
B(A const& a):a_ptr_(new A(a)){}
~B(){ delete a_ptr_; }
void set(A const& a){ a_ptr_ = new A(a); }
private:
A* a_ptr_;
}
class C{
public
C():a_ptr_(NULL){}
C(A const& a):a_ptr_(&a){}
void set(A const& a){ a_ptr_ = &a; }
private:
A* a_ptr_;
}
My problem is that if I do
B b(A(1.0));
C c(A(1.0));
the class A is instanciated twice for B (two creation constructor calls).
C::a_ptr_ is problematic. If I do :
B b;
C C;
{
A a(1.0);
b.set(a);
c.set(a);
}
I have the same problems outside the brackets.
I would like to find a way to store a pointer on A in B or C without
copying the class A too many times and without having undefined pointers.
I've found something with a move constructor but I've never used such.
Any idea ? Thx !
std::shared_ptr is exactly what you need. This class is used for storing one pointer in different places. The target object will be deleted after the last shared_ptr pointing to it is destroyed. Since you are clearing the memory in the destructor, your classes obtain ownership of the A object. You can use something like this:
class B{
public
B():a_ptr_(NULL){}
B(A * a): a_ptr_(a){ }
~B(){}//don't need to do anything here.
void set(A * a){ a_ptr_.reset(a); }
private:
std::shared_ptr<A> a_ptr_;
}
<...>
class C should be written in a similar manner
<...>
A * a = new a(1.0);
B b(a);
C c(a)
Now, if you want to make a constructor or set method that takes a by reference, you will not be able to avoid copying it. Also, in this case you can't safely take the address of this variable.
I have the following C++-class:
// Header-File
class A
{
public:
A();
private:
B m_B;
C m_C;
};
// cpp-File
A::A()
: m_B(1)
{
m_B.doSomething();
m_B.doMore();
m_C = C(m_B.getSomeValue());
}
I now would like to avoid the class A to call any constructor of C m_C. Because on the last line in A::A(), I'm anyways going to initialize m_C myself because I need to prepare m_B first. I could provide an empty default constructor for class B. But that's not the idea.
I have already tried to add m_C(NULL) to the init-list of A::A(). Sometimes it worked, sometimes it said there was no constructor taking NULL as an argument.
So how can I have m_C left uninitialized? I know that with pointers, the m_C(NULL)-way works. And I don't want to allocate it dynamically using new.
Any idea is appreciated.
How about using technique described in this QA?
Prevent calls to default constructor for an array inside class
std::aligned_storage<sizeof(T[n]), alignof(T)>::type
Or, you also can consider using of union. AFAIK, unions will be initialized only with first named member's constructor.
For example,
union
{
uint8_t _nothing = 0;
C c;
};
According to the standard mentioned in the QA, c will be zero-initialized, and its constructor will not be called.
You can't.
All member variables are full constructed when the construcotr code block is entered. This means there constructors must be called.
But you can work around this restriction.
// Header-File
class A
{
struct Initer
{
Initer(B& b)
: m_b(b)
{
m_b.doSomething();
m_b.doMore();
}
operator int() // assuming getSomeValue() returns int.
{
return m_b.getSomeValue();
}
B& m_b;
};
public:
A();
private: // order important.
B m_B;
C m_C;
};
// cpp-File
A::A()
: m_B(1)
, m_C(Initer(m_B))
{
}
I don't see a good way to achieve what you want. This must be a workaround:
// Header-File
class A
{
public:
A();
private:
B m_B;
C m_C;
static int prepareC(B& b);
};
// cpp-File
A::A()
: m_B(1)
, m_C(prepareC(m_B))
{
}
int A::prepareC(B& b)
{
b.doSomething();
b.doMore();
return b.getSomeValue();
}
Please ensure that m_B.doSomething(), m_B.doMore() and m_B.getSomeValue() don't touch m_C (directly or indirectly).
As #Tobias correctly mentions, this solution depends on the order of initialization. You need to ensure that the definitions of m_B and m_C are in this order.
Updated the code according to #Loki's idea.
What you ask is forbidden - and correctly so. This ensures that every member is correctly initialized. Do not try to work around it - try to structure your classes that they work with it.
Idea:
C has a constructor that does nothing
C has an initialization method that makes the class usable
C tracks whether it has been initialized correctly or not and returns appropriate errors if used without initialization.
The pointer sounds like the only clean solution to me. The only other solution I see is to have a default constructor for C that does nothing and have an initialising method in C you call yourself later.
m_C.Initialise( m_B.getSomeValue() );
Easiest is storing pointers to a B and a C. These can be initialized to 0, omitting any construction. Be careful not to dereference a null pointer and delete it in the destructor of A (or use std::unique_ptr/boost::scoped_ptr).
But why not initialize m_B first (through a proper constructor call, not in A::A(), and then use that initialized B instance to initialize m_C? It will call for a small rewrite, but I bet it'll be worth the code cleanup.
If you don't want to allocate it dynamically using new for code clutter/exception safety reasons, you can use a std::unique_ptr or std::auto_ptr to solve this problem.
A solution that avoids new is to edit C to have a two-step initialization process. The constructor would then construct a "zombie" object, and you'd have to call an Initialize method on that m_C instance to finish your initialization. This is similar to the existing cases you found where you could pass NULL to the constructor, and later go back to initialize the object.
Edit:
I thought of this earlier (even though it looks much like other people's solutions). But I had to get some confirmation that this wouldn't break before I added this solution - C++ can be quite tricky, and I don't use it very often :)
This is cleaner than my other suggestions, and doesn't require you to mess with any implementation but that of A.
Simply use a static method as the middle-man on your initialization:
class A
{
public:
A();
private:
static int InitFromB(B& b)
{
b.doSomething();
b.doMore();
return b.getSomeValue();
}
// m_B must be initialized before m_C
B m_B;
C m_C;
};
A::A()
: m_B(1)
, m_C(InitFromB(m_B))
{
}
Note that this means you can't allow m_B to depend on the instance of A or C at all, whereas the solutions at the top of this answer might allow you to pass A or m_C into m_B's methods.
Just use comma expressions:
A::A()
: m_B(1)
, m_c(m_B.doSomething(), m_B.doMore(), m_B.getSomeValue())
{
}
Obviously, as others have explained, m_B better be declared before m_C else m_B.doSomething() invokes undefined behavior.
Here we have the building blocks:
#include <iostream>
class C
{
public:
C(int i){std::cout << "C::C(" << i << ")" << std::endl;}
};
class B
{
public:
B(int i){std::cout << "B::B(" << i << ")" << std::endl;}
void doSomething(){std::cout << "B::doSomething()" << std::endl;}
void doMore(){std::cout << "B::doMore()" << std::endl;}
int getSomeValue(){return 42;}
};
If you want to make a new kind of construction for B consider making a derived class:
class B1 : public B
{
public:
B1() : B(1)
{
doSomething();
doMore();
}
};
Now use the class B1 that is derived from B:
class A
{
private:
B1 _b;
C _c;
public:
A() : _c(_b.getSomeValue()){std::cout << "A::A()" << std::endl;}
};
And then:
int main()
{
A a;
}
Output:
B::B(1)
B::doSomething()
B::doMore()
C::C(42)
A::A()
ok say we have the following classes
class A
{
public:
virtual void taco()
{
cout << "Class A" << endl;
}
};
class B: public A
{
public:
virtual void taco()
{
cout << "Class B" << endl;
}
};
class C : public A
{
public:
void taco()
{
cout << "Class C" << endl;
}
};
Now if I do this
A a = A();
B b = B();
C c = C();
a.taco(); //Class A
b.taco(); //Class B
c.taco(); //Class C
deque<A> aa = deque<A>();
aa.push_back(a);
aa.push_back(b);
aa.push_back(c);
for(int i=0;i<aa.size();i++)
aa[i].taco();//All Class A
A r = B();
r.taco(); //Class A
Now you'll notice when I initialize A as B or C, it won't fire the functions from B or C. I was wondering if there was any way around this? I understand the concept that since the object is A it uses A's taco function, but I was just wondering if there was some trick to getting at the other functions. My project is fairly complicated, and I can't know all the classes that will override A(due to plugins overriding a class). Also, I kinda need to have the base virtual function have a body to add default behavior. Thanks.
You must store pointers in the deque, since polymorphism only works with reference & pointer types. When you insert those objects into the deque, copies are made of type A, "slicing" off the parts that made them B or C originally.
Similarly, A r = B() just creates a temporary B and copies the A part of it into an A called r.
BTW by A a = A(); you might as well write A a;. They're not completely equivalent, but they do the same job here, and you likely meant for the simpler version.
A a;
B b;
C c;
a.taco(); //Class A
b.taco(); //Class B
c.taco(); //Class C
// With pointers and containers
deque<A*> aa;
aa.push_back(&a);
aa.push_back(&b);
aa.push_back(&c);
for (int i=0; i<aa.size(); i++)
aa[i]->taco(); // Hurray!
// With refs
B q;
A& r = q;
r.taco(); // Class B!
(Just remember that those objects a, b and c have automatic storage duration. The moment they go out of scope, if the deque still exists then all its elements are invalid pointers. You may want to employ dynamic allocation to further control the lifetime of the A, B and C objects.. but I'll leave that as an exercise to the reader.)
I'm a PHP developer trying to write some C++.
I'm having trouble with assigning an object as an another object's property. In PHP, I'd write this:
class A {
public $b;
}
class B {
}
$a = new A;
$a->b = new B;
How do I do that in C++? I got this so far:
class A {
B b;
public:
void setB(&B);
};
class B {
};
void A::setB(B &b)
{
this->b = b;
};
A * a = new A();
B * b = new B();
a->setB(b);
What am I doing wrong?
Just do this:
class B
{
};
class A
{
B b;
};
int main()
{
A anA; // creates an A. With an internal member of type B called b.
// If you want a pointer (ie using new.
// Then put it in a smart pointer.
std::auto_ptr<A> aPtr = new A();
}
You don't actually need to create the B separately. The B b is part of the class and is created (using the default constructor) automatically when the A object is created. Creating the two objects seprately and then combining them is a bad idea.
If you want to pass some parameters to the B object as it is constructed. That is easy to do by creating a constructor for A that calls B's constructor:
class B
{
public:
B(std::string const& data) // The B type takes a string as it is constructed.
:myData(data) // Store the input data in a member variable.
{}
private:
std::string myData;
};
class A
{
public:
A(std::string const& bData) // parameter passed to A constructor
:b(bData); // Forward this parameter to `b` constructor (see above)
{}
private:
B b;
};
int main()
{
A a("Hi there"); // "Hi there" now stored in a.b.myData
}
Instead of &B, you mean B&.
class A {
B b;
public:
void setB(B&); //<--
};
A pointer cannot be implicitly dereferenced. So a->setB(b) won't compile. You need to write a->setB(*b).
You don't need new to construct an object. For example, this works:
A a;
B b;
a.setB(b);
Don't use idioms from other languages directly in C++. For example, setters and getters are seldom needed. In fact, your A class could just be a simple struct.
A couple changes will make it compile:
1. class B needs to be declared before A so that it can be used in class A
2. The declaration setB(&B) needs a minor change to setB(B&)
class B {
};
class A {
B b;
public:
void setB(B&);
};
void A::setB(B &b)
{
this->b = b;
};
int main ()
{
A * a = new A();
B * b = new B();
a->setB(*b);
}
To make it more efficient consider the adding the following constructor that accepts B as an argument and the initializes the member variable 'b'. This will use a copy constructor on the 'b' member variable instead of using the default constructor and then the assignment operator.
A(B& b_) : b(b_)
{
}
There are a lot of things wrong with this code:
As KennyTM notes, the ampersand is in the wrong place.
You are passing a B* to a function that takes a B&, they aren't the same in C++
The design shown in your php fragment appears to misdesigned. While what you are doing is something you might want to do at times, you'll usually want to use a constructor instead, C++ and PHP alike.
You are putting code directly in the file, this isn't allowed in C++, put it in the main function instead
memory management: you are using new without delete (or a smart pointer class)
You are using class B in class A while class A doesn't know about class B (it is defined later) - you should put class B on top (or perhaps use forward declaration)
A few ways to make your code work properly are shown below.
include <memory>
using std::auto_ptr;
class B
{
}
class A
{
public:
A();
SetB(B& b);
private:
B b1; // a B made in the constructor
B b2; // a COPY of the original B you make
}
A::A()
: b1(/*whatever you want to pass to B's constructor*/)
{
}
A::SetB(B& b)
{
b2 = b;
}
int main(int agrc, char** argv)
{
A firstA();
B firstB();
firstA.SetB(firstB);
A* secondA = new A();
B* secondB = new B();
secondA->SetB(*secondB);
auto_ptr<A> thirdA(new A());
auto_ptr<B> thirdB(new B());
thirdA->SetB(*thirdB);
// whatever other code
delete secondA;
delete secondB;
}
Note that id you call SetB only once (and there is no problem with cyclic depndencies between the different objects you are creating), but you do want the flexibility of constructing the B outside the class, you can instead make a parameter of the constructor.
Also note that you are making a copy of the B you create in main - if you want to use the came copy in the class (as you would in PHP), you should use a member reference (in which case you will need to set what it refers to in the constructor, you can't do so in the SetB function.
Then, note that there are serious problems with the secondA, secondB approach and as such it is not recommended (above nothing will go wrong, however, it is easy to get code that leaks memory this way (and hard to find out where the leak is) and on top of that when you want to use exceptions, you will need exception safe code, which is not achievable using plain old pointers.
Lastly, note that you mix and match here. There is no problem at all with using firstA and thirdB together, for example.