[ACCEPTED]-Why explicitly call a constructor in C++-constructor
You also sometimes explicitly use a constructor 21 to build a temporary. For example, if you 20 have some class with a constructor:
class Foo
{
Foo(char* c, int i);
};
and a 19 function
void Bar(Foo foo);
but you don't have a Foo around, you 18 could do
Bar(Foo("hello", 5));
This is like a cast. Indeed, if 17 you have a constructor that takes only one 16 parameter, the C++ compiler will use that 15 constructor to perform implicit casts.
It 14 is not legal to call a constructor on an already-existing 13 object. That is, you cannot do
Foo foo;
foo.Foo(); // compile error!
no matter 12 what you do. But you can invoke a constructor 11 without allocating memory - that's what 10 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 9 constructs the object in that spot instead 8 of allocating new memory. This usage is 7 considered evil, and is rare in most types 6 of code, but common in embedded and data 5 structure code.
For example, std::vector::push_back
uses this 4 technique to invoke the copy constructor. That 3 way, it only needs to do one copy, instead 2 of creating an empty object and using the 1 assignment operator.
Most often, in a child class constructor 5 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 4 than that, I don't see the utility. I only 3 did call the constructor in other code when 2 I was too young to know what I was really 1 doing...
I think the error message for compiler error 13 C2585 gives the best reason why you would 12 need to actually use the scope-resolution 11 operator on the constructor, and it does 10 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 9 have BaseClass, and BaseClassA and BaseClassB 8 both inherit BaseClass, and then DerivedClass 7 inherits both BaseClassA and BaseClassB.
If 6 you are doing a conversion or operator overload 5 to convert DerivedClass to a BaseClassA 4 or BaseClassB, you will need to identify 3 which constructor (I'm thinking something 2 like a copy constructor, IIRC) to use in 1 the conversion.
In general you do not call the constructor 10 directly. The new operator calls it for 9 you or a subclass calls the parent class' constructors. In 8 C++, the base class is guarenteed to be 7 fully constructed before the derived class' constructor 6 starts.
The only time you would call a constructor 5 directly is in the extremely rare case where 4 you are managing memory without using new. And 3 even then, you shouldn't do it. Instead 2 you should use the placement form of operator 1 new.
I don't think you would typically use that 15 for the constructor, at least not in the 14 way you're describing. You would, however, need 13 it if you have two classes in different 12 namespaces. For example, to specify the 11 difference between these two made-up classes, Xml::Element
and 10 Chemistry::Element
.
Usually, the name of the class is used 9 with the scope resolution operator to call 8 a function on an inherited class's parent. So, if 7 you have a class Dog that inherits from 6 Animal, and both of those classes define 5 the function Eat() differently, there might 4 be a case when you want to use the Animal 3 version of eat on a Dog object called "someDog". My 2 C++ syntax is a little rusty, but I think 1 in that case you would say someDog.Animal::Eat()
.
There are valid use cases where you want 35 to expose a classes constructors. If you 34 wish to do your own memory management with 33 an arena allocator for example, you'll need 32 a two phase construction consisting of allocation 31 and object initialization.
The approach 30 I take is similar to that of many other 29 languages. I simply put my construction 28 code in well known public methods (Construct(), init(), something 27 like that) and call them directly when needed.
You 26 can create overloads of these methods that 25 match your constructors; your regular constructors 24 just call into them. Put big comments in 23 the code to warn others that you are doing 22 this so they don't add important construction 21 code in the wrong place.
Remember that there 20 is only one destructor method no matter 19 which construction overload was used, so 18 make your destructors robust to uninitialized 17 members.
I recommend against trying to 16 write initializers that can re-initialize. It's 15 hard to tell the case where you are looking 14 at an object that just has garbage in it 13 because of uninitialized memory vs. actually 12 holding real data.
The most difficult issue 11 comes with classes that have virtual methods. In 10 this case the compiler normally plugs in 9 the vtable function table pointer as a hidden 8 field at the start of the class. You can 7 manually initialize this pointer, but you 6 are basically depending on compiler specific 5 behavior and it's likely to get your colleagues 4 looking at you funny.
Placement new is broken 3 in many respects; in the construction/destruction 2 of arrays is one case so I tend not to use 1 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 2 call a default constructor explicitly to 1 initialize the variable.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.