What Are the Rules For Calling the Base Class Constructor

What are the rules for calling the base class constructor?

Base class constructors are automatically called for you if they have no argument. If you want to call a superclass constructor with an argument, you must use the subclass's constructor initialization list. Unlike Java, C++ supports multiple inheritance (for better or worse), so the base class must be referred to by name, rather than "super()".

class SuperClass
{
public:

SuperClass(int foo)
{
// do something with foo
}
};

class SubClass : public SuperClass
{
public:

SubClass(int foo, int bar)
: SuperClass(foo) // Call the superclass constructor in the subclass' initialization list.
{
// do something with bar
}
};

More info on the constructor's initialization list here and here.

How do I call the base class constructor?

You do this in the initializer-list of the constructor of the subclass.

class Foo : public BaseClass {
public:
Foo() : BaseClass("asdf") {}
};

Base-class constructors that take arguments have to be called there before any members are initialized.

How to get around calling base class constructor from derived class with the same arguments?

You may use a using-declaration to

Using-declaration

[...] introduce base class members into derived class definitions.

[...]

Inheriting constructors

If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using Base::Base;), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.

If overload resolution selects an inherited constructor, it is accessible if it would be accessible when used to construct an object of the corresponding base class: the accessibility of the using-declaration that introduced it is ignored.

as such:

class B : public A {
using A::A;
};

Note the highlight that the accessibility of the using-declaration itself is ignored, meaning using A::A in the example needn't the be placed under public accessibility - what matters is the accessibility of the inherited constructors in B.

How to avoid calling the base class constructor

A constructor of the base class is always used - but when the base class has no explicitly defined constructor, C# will generate a public parameterless constructor automatically.

Similarly, if you don't explicitly mention : base(...) in your derived class, C# assumes you want to use the parameterless constructor of the base class.

As soon as you define a constructor, the parameterless constructor is not automatically generated anymore, and so you have to call : base(...).

You can easily change this by adding such a constructor to the base class:

public class ExportData
{
protected ExportData()
{
}
}

By making this constructor protected, only classes that inherit from ExportData can use this constructor, and they no longer have to include : base(...).

derived class constructor call base constructor

Since size is a private variable in the base class Array, it cannot be accessed in the child class NumericArray.

There are two ways to access size in the child class NumericArray:

  1. Make size a protected variable in the base class Array and access it in the child class NumericArray.

    protected: int size;
  2. Write a getter public function (GetSize()) in the base class Array that returns size, and the child class NumericArray can just call this getter public function in the constructor of the child class using super.GetSize() per this link.

    public:
    GetSize() { return size }

Can I call a derived class constructor from a base class?

You cannot call a derived class constructor from a base class. The base class has no idea the derived class even exist.

Why is user defined copy constructor calling base constructor while default copy constructor doesn't? [duplicate]

Why is the constructor of A is called when copying B? Shouldn't the copy constructor of A be called instead?

No, it shouldn't.

A derived class must always initialize a base class. If the derived class has a constructor that is implemented explicitly by the user, but it does not explicitly call a base class constructor in its member initialization list, the compiler will make an implicit call to the base class's default constructor, regardless of the type of the derived constructor. The compiler does not make any assumption about the user's intent in implementing the derived constructor. If the user wants a specific base class constructor to be called, they need to make that call themselves.

Since B has an explicitly implemented copy constructor that lacks a member initialization list, the compiler initializes A by calling its default constructor, not its copy constructor.

IOW, this:

B(B const& other)
{
...
}

Is equivalent to this:

B(B const& other) : A()
{
...
}

NOT to this, as you are thinking:

B(B const& other) : A(other)
{
...
}

However, if you change class B's copy constructor to be default, the constructor of A is not called when copying which makes sense.

Correct, a default'ed copy constructor will call the base class's copy constructor, not its default constructor. The compiler is implicitly implementing the entire derived constructor, and so it will choose the appropriate base class constructor to call.



Related Topics



Leave a reply



Submit