I am primarily a c# programmer but a project I am working on has me using c++. In C# I have the ability to define a member of a class where the member is null until it is initialized. Like so:
Class Foo{
private Bar _bar;
public Foo(int valueBarNeeds){
_bar = new Bar(valueBarNeeds);
}
}
The value of _bar is null and access is prohibited until it is initialized. The rationale for this use case is that the constructor for the private object relies on some value that is not known until the parent class is constructed.
Now, in C++ I try and do the same thing:
class Foo{
public:
Foo(int valueBarNeeds){
_bar = new Bar(valueBarNeeds);
}
private;
Bar _bar;
};
The compiler throws an error saying that there is no constructor for bar that takes zero arguments. My understanding is, in C++ the new keyword means something completely different. As a part of this difference, one is able to define objects that get disposed at the end of a method without needing a manual deletion by declaring without the new keyword.
SomeFunc(){
int valueBarNeeds = 100;
Bar _bar(valueBarNeeds);
_bar.SomeFunc();
}
_bar is deleted when the methods stack goes out of scope.
This then sets up my question. If the syntax that I use in C# to create unitialized objects actually tries to initialize objects in C++... How do I create an unitialized type accesible to the rest of the class methods, that gets built by the parent objects constructor?
The problem is that what you're calling "initialisation" is actually no such thing. Any members that are initialised, implicitly or explicitly, are initialised before the program enters your constructor body.
Your code snippets show only assignment; it doesn't matter that you're doing this in the body of a constructor for the encapsulating object. It's still just assignment.
Bar is a class so your member _bar will be implicitly initialised, but it actually cannot be because the class has no constructor taking no arguments. In order to provide arguments, you have to explicitly initialise the member yourself.
In C++ we initialise members like this:
class Foo {
public:
Foo(int valueBarNeeds)
: _bar(valueBarNeeds)
{}
private:
Bar _bar;
};
You are also right in that you are misunderstanding new a little; unlike in Java, it should be used sparingly, as objects are fundamentally created by simply declaring (and, where necessary, defining) them. The use of new is reserved for dynamic allocation in the free store and returns a pointer for use; this usage should be rare. You successfully fixed this in your final code snippet.
How do I create an unitialized type accesible to the rest of the class methods, that gets built by the parent objects constructor?
If the member is of a class type, it will always be initialised. You can't have an object that doesn't exist. The closest you can get is to encapsulate a pointer rather than an object:
class Foo {
public:
Foo(int valueBarNeeds)
: _bar(nullptr)
{
// some time later...
_bar = new Bar(valueBarNeeds);
}
private:
Bar* _bar;
};
But this opens up a can of worms as regards memory management and whatnot and, as explained above, you should avoid it unless you really need it. Alternatives include smart pointers but you should still consider sticking with the bog-standard object encapsulation where possible. It should be rare that you need to deliberately leave an object in an invalid state for a time.
You give your class a data member of that type, and initialize it in the constructor's initialization list:
class Foo
{
public:
Foo(int valueBarNeeds) :_bar(valueBarNeeds) {}
private:
Bar _bar;
};
Once you are in the constructor's body, all data members have been initialized. If you do not initialize them explicitly in the constructor initialization list, they get default initialized, which means the default constructor is called for user defined types, and no initialization is performed for built-in types.
Related
I know we can explicitly call the constructor of a class in C++ using scope resolution operator, i.e. className::className(). I was wondering where exactly would I need to make such a call.
You also sometimes explicitly use a constructor to build a temporary. For example, if you have some class with a constructor:
class Foo
{
Foo(char* c, int i);
};
and a function
void Bar(Foo foo);
but you don't have a Foo around, you could do
Bar(Foo("hello", 5));
This is like a cast. Indeed, if you have a constructor that takes only one parameter, the C++ compiler will use that constructor to perform implicit casts.
It is not legal to call a constructor on an already-existing object. That is, you cannot do
Foo foo;
foo.Foo(); // compile error!
no matter what you do. But you can invoke a constructor without allocating memory - that's what placement new is for.
char buffer[sizeof(Foo)]; // a bit of memory
Foo* foo = new(buffer) Foo(); // construct a Foo inside buffer
You give new some memory, and it constructs the object in that spot instead of allocating new memory. This usage is considered evil, and is rare in most types of code, but common in embedded and data structure code.
For example, std::vector::push_back uses this technique to invoke the copy constructor. That way, it only needs to do one copy, instead of creating an empty object and using the assignment operator.
Most often, in a child class constructor that require some parameters :
class BaseClass
{
public:
BaseClass( const std::string& name ) : m_name( name ) { }
const std::string& getName() const { return m_name; }
private:
const std::string m_name;
//...
};
class DerivedClass : public BaseClass
{
public:
DerivedClass( const std::string& name ) : BaseClass( name ) { }
// ...
};
class TestClass :
{
public:
TestClass( int testValue ); //...
};
class UniqueTestClass
: public BaseClass
, public TestClass
{
public:
UniqueTestClass()
: BaseClass( "UniqueTest" )
, TestClass( 42 )
{ }
// ...
};
... for example.
Other than that, I don't see the utility. I only did call the constructor in other code when I was too young to know what I was really doing...
I think the error message for compiler error C2585 gives the best reason why you would need to actually use the scope-resolution operator on the constructor, and it does in with Charlie's answer:
Converting from a class or structure type based on multiple inheritance. If the type inherits the same base class more than once, the conversion function or operator must use scope resolution (::) to specify which of the inherited classes to use in the conversion.
So imagine you have BaseClass, and BaseClassA and BaseClassB both inherit BaseClass, and then DerivedClass inherits both BaseClassA and BaseClassB.
If you are doing a conversion or operator overload to convert DerivedClass to a BaseClassA or BaseClassB, you will need to identify which constructor (I'm thinking something like a copy constructor, IIRC) to use in the conversion.
In general you do not call the constructor directly. The new operator calls it for you or a subclass calls the parent class' constructors. In C++, the base class is guarenteed to be fully constructed before the derived class' constructor starts.
The only time you would call a constructor directly is in the extremely rare case where you are managing memory without using new. And even then, you shouldn't do it. Instead you should use the placement form of operator new.
I don't think you would typically use that for the constructor, at least not in the way you're describing. You would, however, need it if you have two classes in different namespaces. For example, to specify the difference between these two made-up classes, Xml::Element and Chemistry::Element.
Usually, the name of the class is used with the scope resolution operator to call a function on an inherited class's parent. So, if you have a class Dog that inherits from Animal, and both of those classes define the function Eat() differently, there might be a case when you want to use the Animal version of eat on a Dog object called "someDog". My C++ syntax is a little rusty, but I think in that case you would say someDog.Animal::Eat().
There are valid use cases where you want to expose a classes constructors. If you wish to do your own memory management with an arena allocator for example, you'll need a two phase construction consisting of allocation and object initialization.
The approach I take is similar to that of many other languages. I simply put my construction code in well known public methods (Construct(), init(), something like that) and call them directly when needed.
You can create overloads of these methods that match your constructors; your regular constructors just call into them. Put big comments in the code to warn others that you are doing this so they don't add important construction code in the wrong place.
Remember that there is only one destructor method no matter which construction overload was used, so make your destructors robust to uninitialized members.
I recommend against trying to write initializers that can re-initialize. It's hard to tell the case where you are looking at an object that just has garbage in it because of uninitialized memory vs. actually holding real data.
The most difficult issue comes with classes that have virtual methods. In this case the compiler normally plugs in the vtable function table pointer as a hidden field at the start of the class. You can manually initialize this pointer, but you are basically depending on compiler specific behavior and it's likely to get your colleagues looking at you funny.
Placement new is broken in many respects; in the construction/destruction of arrays is one case so I tend not to use it.
Consider the following program.
template<class T>
double GetAverage(T tArray[], int nElements)
{
T tSum = T(); // tSum = 0
for (int nIndex = 0; nIndex < nElements; ++nIndex)
{
tSum += tArray[nIndex];
}
// Whatever type of T is, convert to double
return double(tSum) / nElements;
}
This will call a default constructor explicitly to initialize the variable.
I need a parent class to have a pointer to a child class' struct member. Is it possible to solve this during initialization as shown below, or will the address to _foo not be available/be invalid?
struct Foo { int a; int b; }
class A {
public:
A(void* fooHandle) : _fooHandle(fooHandle) {}
private:
void* _fooHandle;
};
class B : public A {
public:
B() : A(&_foo) {
/* _foo initialized here */
}
private:
Foo _foo;
};
Is this code safe? I.e. will &_foo give a valid address? Of course I mean according to the standard, not whether it may work for some compilers.
Yes, this is perfectly safe.
EDIT (explanation): The storage for the object is allocated before any constructor is called. Objects occupy a region of storage that has one start and one end address. There may be gaps inbetween (padding). However for the whole lifetime of an object, all it's members are alive as well. When the constructors are called (eventually) all member objects part of the class the constructor of which is called, already live (by constructor I mean the part between {…}). This is why, if you need initialization before constructor execution you have to provide initializers. Members are initialized in the order as it appears in the class and you'll get severe warnings if initializers appear in a different order, so as long as you pass addresses to members, which went through initialization, you're within the lifetime of these members.
In the same way the lifetime of members ends only after all destructors were called.
Of course anything created with new and destroyed with delete has lifetimes that are not tied to class instance lifetimes, so you've to be careful with that.
However I wonder what the practical application of this is. Also I'd suggest to use a reference instead of a pointer to enforce passing a valid object and also making the constructor protected, so that it can be used only from child classes.
I have two classes
class A {
public:
virtual void doStuff() = 0;
};
class B : public A {
int x;
public:
virtual void doStuff() override { x = x*2;} //just example function
};
And another class that modify and use data from the previous
class Foo {
A a;
public:
Foo::Foo(A &a_) : a(a_) {}
};
now I create the objects, and passes to the Foo class
B b;
// edit b attributes,
Foo foo(b);
So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?
Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.
Will there be a object slicing?,
Is there a solution to this, or I need to pass pointers (don't want this approach)?
This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.
In fact:
class Foo {
A a;
that won't even compile, because A is not a concrete class.
To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.
Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.
This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.
All of this is harder than just using the built in C++ object model directly, but it can have payoff.
To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.
There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors.
Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.
You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.
Yes, there is slicing.
There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.
I am a bit confused, i was reading this C++ Constructor/Destructor inheritance, and so it says constructors and destructors are not inherited from the base class to the derived class but the constructors and destructors are called when i create a derived object. So is the constructors and destructors of the base class data members of the inherited classes?
Constructors and destructors are very special animals; in fact, the Standard identifies them as "Special Member Functions."
All the things that are weird and unique about constructors and destructors (for example, the fact that they don't have "names" and the fact that they aren't "inherited") is really quite irrelevant to almost all programming and programmers. Here is what you need to know:
Constructors and destructors are not member variables (obviously) -- they are (special) member functions.
When you derive from a base class, some constructor of the base class is going to be called. Which constructor depends on how you've written your code. If you don't explicitly specify which constructor to call, the default constructor will be called. This happens in your derived object's initialization list, even if you haven't written one.
You may specify another constructor through an initialization list, only:
class Bar : public Foo
{
public:
Bar()
:
Foo (1, 2, 3)
{
}
};
Here, Bar's initialization list specifies a constructor on Foo which takes 3 parameters convertible from integrals. One such constructor might be:
class Foo
{
public:
Foo (int a, long b, unsigned c)
:
mA (a),
mB (b),
mC (c)
{
}
private:
int mA;
long mB;
unsigned mC;
};
Back to the Bar example above. By the time the initialization list is done executing, and before the body of Bar's constructor starts, all of Bar's base classes and member variables have already been instantiated and initialized. This is why the only way to specify some constructor for Foo other than the default constructor is through an initialization list -- which, in turn, is why you must have an initialization list if the base class has no default constructor available.
Question: If constructors and destructors are not inherited, then why are they called when instantiating a derived type?
Answer: Because constructors are what initialize objects, and a derived type has an IS-A relationship with the base type.
Consider Foo and Bar above again. Bar derives from Foo, so in a sense Bar IS A Bar. It's more than just a Foo, it's got stuff that Foo doesn't have; but it has all the Foo-ness. Since a Bar object is in part a Foo, that Foo-ness has to be initialized. Since all initialization ob objects is done through a constructor, Foo's constructor must be called.
So, constructors and destructors aren't inherited in the sense of overloading -- but the constructors of the base class will be called. They have to be. Otherwise the Fooness of a Bar object could never come to be.
When you are deriving from a base class, something that you will often want to do is pass around a pointer to the base class. In fact, you may not need a pointer to the derived type at all in many cases. This is especially true when designing abstract interfaces.
There is a nasty problem that can come up when you do this and haven't taken all the needed preperations. Consider:
class Foo
{
public:
std::string mS;
};
class Bar : public Foo
{
public:
long mArray[0xFFFF]; // an array of 65K longs
};
int main()
{
Foo* thingy = new Bar; // Totally OK
// ... do stuff...
delete thingy; // WHOOPS! Memory leak!
}
Above in the delete call we're deleting through a base class pointer. The Foo destructor (which is implicit) is properly called, but the Bar destructor is not -- leaving that huge array of 65K longs leaked.
To fix this, we need to give Foo a virtual destructor:
class Foo
{
public:
std::string mS;
virtual ~Foo() {}
};
This doesn't do much, but it does one critical thing: it sets up polymorphism so that when we call the destructor (implicitly), the virtual override will get called.
This is a critical step when designing a class hierarchy. If you think there is any chance that people will pass around pointers to the base class, you should have a virtual destructor in the base class. In fact, I would suggest that in almost every case you should have a virtual destructor even if you don't think people will use it this way.
No. As you said, constructors and destructors are not inherited (by the way, the assignment operator isn't either). It would be logically flawed if they were inherited, right? Constructors (and destructors) are specific for that exact class; and since the derived class usually has something specific and new, the base constructor is not enough to initialize the inherited class objects.
So why is the base constructor called when creating an object of the child class?
Well, every derived object has a sub-object - which is the actual object of the parent class (I hope this sentence wasn't difficult to understand).
The compiler will:
1) locate the constructor of the derived class whose list of initializers best fits the arguments passed, but not execute it;
2) execute the constructor of the base class to create the sub-object;
3) execute the constructor of the derived class, to create the actual object.
I hope this is clear; you can find a much more detailed explanation in the answer above :)
Observation: The constructor of ClassMain needs to call Init before it can constructor a member variable a. Since the ClassA has no default constructor, the code doesn't compile.
ClassA
{
public:
// This class has no default constructor
ClassA(...){}
};
class ClassMain
{
public:
ClassMain(...) {
Init(...);
a = ClassA(...); // error: ClassA has no default constructor
// a has to been constructed after the Init is called!
}
ClassMain(...) {
Init(...);
call other functions
a = ClassA(...);
}
private:
// initialize environment
void Init(...) {}
private:
ClassA a;
};
Question> The simple solution is to provide a default constructor for ClassA. However, I would like to know whether there is a better solution to address the issue above?
The better solution is not to require an Init function at all. You're trying to reinvent constructors, and breaking their design in the process.
If Init does too much work for a constructor, then do it outside and pass the resulting resources into ClassMain as a constructor argument; notice how you're already doing all the work in the constructor's scope anyway, thereby not gaining anything appreciable over proper initialisation.
Of course, if you must perform a ton of work before initialising a, and you cannot pass in a ClassA& from the outside and initialise from that, then you're simply going to have to have a be an indirect member.
There is one nasty workaround you could use: have Init actually be a base constructor...
The obvious solution is to call Init() from the initializer list of an early member or a base class. Once this subobject is constructed its results can be passed to the constructors of other subobjects. For example, when defining stream classes I typically privately inherit from a virtual base containing the stream buffer:
struct somebuf_base {
somebuf sbuf;
// ...
};
class somestream
: private virtual somebuf_base
, public std::ostream
{
public:
somestream(someargs)
: somebuf_base(someargs)
, std::ostream(&this->sbuf) {
}
// ...
};
Since base classes are constructed in the order they appear but virtual bases before non-virtual bases, the base class containing the sbuf member is constructed first. Its constructor replaces your Init() function.
When using C++ as of the 2011 revision, you might also use forwarding constructors to share logic between multiple constructors.
It's easier to take a pointer to ClassA; So, you can instantiate it whenever you want.(after the init())
If you used a pointer, don't forget to implement the virtual destructor and release the allocated memory for the ClassA *a
If you absolutely must call some function at the start of your constructor, and can't put that setup into some base class or early-constructed member, you could use this ugly trick:
ClassMain::ClassMain(int main_param)
: a( (Init(init_arg), class_a_arg1), class_a_arg2 )
{
}
In this case: No, we cannot avoid that.
The reason is that when calling Init or any other member function you are guaranteed by the language that the object you are in exists. As a is a member of ClassMain it must be constructed before any function in ClassMain can be called.
The only chance that you have here is to refactor the code.