Calling Constructor of a Class Member in Constructor

calling constructor of a class member in constructor

Yes, certainly you can! That's what the constructor initializer list is for. This is an essential feature that you require to initialize members that don't have default constructors, as well as constants and references:

class Foo
{
Bar x; // requires Bar::Bar(char) constructor
const int n;
double & q;
public:
Foo(double & a, char b) : x(b), n(42), q(a) { }
// ^^^^^^^^^^^^^^^^^^^
};

You further need the initializer list to specify a non-default constructor for base classes in derived class constructors.

Calling a constructor of a member object within the body of the constructor?

The problem is that when C++ begins the execution of the constructor code all the member variables must have been already constructed (what if you for example call a method of Circle before constructing it?).

If immediate construction is a problem then a possible solution is to add to your member a default constructor and the using assignment in the body of the constructor of the containing class.

You can imagine that native types like int or double do have a default constructor, that's why you can initialize them later (note however that for one of the many ugly quirks of the language the default constructor for an int or a double doesn't actually do anything in this case and you're not allowed to do anything with such a member except assigning it a value - for example reading it is not allowed).

You cannot use base(r) in the body because that's not a valid statement... following a name with an opening parenthesis is only used for function call, for initialization in a declaration or for member initialization in the constructor member initialization list.

If you provide Circle with a default constructor then you can do

Cylinder(double r, double h) {
base = Circle(r);
height = h;
}

Note however that the approach of constructing non-working objects to fix them later is not the best approach for C++. The language likes the idea that if an object is constructed then it's usable and deviations from this are considered only when necessary (C++11 drifted away a bit from this original path with move constructor... but that's another story).

How do I call one constructor from another in Java?

Yes, it is possible:

public class Foo {
private int x;

public Foo() {
this(1);
}

public Foo(int x) {
this.x = x;
}
}

To chain to a particular superclass constructor instead of one in the same class, use super instead of this. Note that you can only chain to one constructor, and it has to be the first statement in your constructor body.

See also this related question, which is about C# but where the same principles apply.

Calling Constructor with in constructor in same class

Inside this constructor:

A(int x, int y)
{
a = x;
b = y;
A(); // calling the default constructor
}

call A(); creates a new temporary object that is immediately deleted after this statement. Because the default constructor A() does not initializes data members a and b then it outputs a garbage.

This temporary object has nothing common with the object created by constructor A( int, int ).

You could rewrite your class the following way:

class A
{
public:
int a, b;

A(): A(0, 0) {}

A(int x, int y) : a(x), b(y)
{
cout << a << " " << b;
}
};

Calling constructor of class member when using malloc

malloc is a C function, and has no knowledge of classes, constructors, etc.

If you are dead-set on using this, you are going to have to always call placement new on each object (note: this requires including the header <new>), and also manually calling the destructor before deallocating. You will also need to store the pointer that is returned from placement new in order to avoid undefined behavior (as this is technically the only pointer that points to the start of the object's lifetime).

As you have in your edit, it will look something like:

auto cls = static_cast<MyClass*>(std::malloc(sizeof(MyClass)));
cls = new(cls) MyClass(/* any arguments here ... */);
cls->value = "hello";

cls->~MyClass();
std::free(cls);

However, be aware that by using malloc you actually introduce other issues with respect to exception safety. If your placement-new call throws an exception, the memory allocated by std::malloc will leak -- which is bad. You also wouldn't want placement new to operate on nullptr if malloc returns null, and would need to convey this error -- perhaps through an exception. You will probably want to wrap this into a helper that will ensure these conditions can't happen:

#include <new>     // placement-new, std::bad_alloc
#include <utility> // std::forward
#include <cstdlib> // std::malloc, std::free

template <typename T, typename...Args>
T* make(Args&&...args)
{
auto* p = static_cast<T*>(std::malloc(sizeof(T)));

// Placement new can't operate on nullptr
if (p == nullptr) {
// alternatively, this could be 'return nullptr' if not using exceptions
throw std::bad_alloc{};
}

try {
p = new (p) T(std::forward<Args>(args)...);
} catch (...) {
std::free(p);
throw; // rethrow the exception here
}
return p;
};

Similarly, you will likely want to have a way to destroy objects while deallocating them, so that resources aren't leaked:

template <typename T>
void dispose(T* p)
{
p->~T();
std::free(p);
}

Using these utilities, the above example now becomes:

auto cls = make<MyClass>(/* any arguments here ... */);
cls->value = "hello";

dispose(cls);

If this seems like an awful lot of boilerplate, this is because this is exactly what new and delete already does for you. If you can, you will be much better off using these facilities when dealing with C++ types. This also allows you to continue using other RAII-wrappers like smart pointers easily without having to manually specify allocators (shared_ptr) or deleters (unique_ptr).

There really isn't a good reason IMO to prevent using new and delete in favor of malloc/free when working with C++ code. If you have a library that exposes a C-only interface but is implemented in C++ code -- it would actually be better for you to internalize the allocations and switch to new and delete rather than using malloc and free so you can save yourself the hassle.1

One other thing to be aware of is that if the types allocated in your system ever have a custom alignment via alignas that exceeds alignof(std::max_align_t), using std::malloc will be undefined behavior because it will be unable to satisfy the alignment requirements. This is another thing that new/delete would take care of for you.


1 If your "mixed C++/C" code is exposing a C interface at some point, it would be much cleaner for you to use new and delete rather than malloc, and to simply expose the creation/deletion functions on your API explicitly. For example:

// C header:

extern "C"
my_class* make_my_class(void);

extern "C"
void dispose_my_class(my_class* p);

// C++ implementation:

extern "C"
my_class* make_my_class(void)
{
return new my_class{ ... };
}

extern "C"
void dispose_my_class(my_class* p)
{
delete p;
}

This is generally the approach taken for C/C++ interop.

Call constructor after declaration of a class variable

Members are created as soon as the object is created. As such, the constructor of Vector has already been called on each of the three member vectors.

What you can do, assuming the vector is assignable, is construct a temporary vector, and assign it to a member:

eye = {a, b};

Can I call a constructor from another constructor (do constructor chaining) in C++?

C++11: Yes!

C++11 and onwards has this same feature (called delegating constructors).

The syntax is slightly different from C#:

class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};

C++03: No

Unfortunately, there's no way to do this in C++03, but there are two ways of simulating this:

  1. You can combine two (or more) constructors via default parameters:

    class Foo {
    public:
    Foo(char x, int y=0); // combines two constructors (char) and (char, int)
    // ...
    };
  2. Use an init method to share common code:

    class Foo {
    public:
    Foo(char x);
    Foo(char x, int y);
    // ...
    private:
    void init(char x, int y);
    };

    Foo::Foo(char x)
    {
    init(x, int(x) + 7);
    // ...
    }

    Foo::Foo(char x, int y)
    {
    init(x, y);
    // ...
    }

    void Foo::init(char x, int y)
    {
    // ...
    }

See the C++FAQ entry for reference.

When will C++ call the constructor on an object that is a class member?

Use the ctor-initializer. Members are initialized after base classes and before the constructor body runs.

MyClass::MyClass() : myObject(1,2,3) {
...
}

C++ Trying to pass Class to Constructor of Another Class

    // declare the variable that I want to store Class1 in
Class1 stored_class;

You have a class member called stored_class1. Now, let's take a look at your constructor:

Class2::Class2(Class1 storeClass1)
{

This constructor fails to initialize the stored_class member. It does have a Class1 parameter. That's great, but just because a constructor has a parameter doesn't mean that the constructor will initialize a class member of the same type, automatically. You are responsible for doing this, yourself:

Class2::Class2(Class1 storeClass1)
: stored_class{storeClass1}
{


Related Topics



Leave a reply



Submit