如何调用基类构造函数?

最近,我用 Java 编写了很多程序。在这里,您可以使用 super().调用从中继承的类(您可能都知道这一点)

现在我有一个 C + + 类,它有一个带参数的缺省构造函数,例如:

class BaseClass {
public:
BaseClass(char *name); ....

如果我继承了这个类,它会提醒我没有合适的缺省构造函数可用。那么,在 C + + 中是否有类似于 super()的东西,或者我必须定义一个函数来初始化所有的变量?

166796 次浏览

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.

You have to use initiailzers:

class DerivedClass : public BaseClass
{
public:
DerivedClass()
: BaseClass(<insert arguments here>)
{
}
};

This is also how you construct members of your class that don't have constructors (or that you want to initialize). Any members not mentioned will be default initialized. For example:

class DerivedClass : public BaseClass
{
public:
DerivedClass()
: BaseClass(<insert arguments here>)
, nc(<insert arguments here>)
//di will be default initialized.
{
}


private:
NeedsConstructor nc;
CanBeDefaultInit di;
};

The order the members are specified in is irrelevant (though the constructors must come first), but the order that they will be constructed in is in declaration order. So nc will always be constructed before di.

Use the name of the base class in an initializer-list. The initializer-list appears after the constructor signature before the method body and can be used to initialize base classes and members.

class Base
{
public:
Base(char* name)
{
// ...
}
};


class Derived : Base
{
public:
Derived()
: Base("hello")
{
// ...
}
};

Or, a pattern used by some people is to define 'super' or 'base' yourself. Perhaps some of the people who favour this technique are Java developers who are moving to C++.

class Derived : Base
{
public:
typedef Base super;
Derived()
: super("hello")
{
// ...
}
};

Regarding the alternative to super; you'd in most cases use use the base class either in the initialization list of the derived class, or using the Base::someData syntax when you are doing work elsewhere and the derived class redefines data members.

struct Base
{
Base(char* name) { }
virtual ~Base();
int d;
};


struct Derived : Base
{
Derived() : Base("someString") { }
int d;
void foo() { d = Base::d; }
};

There is no super() in C++. You have to call the Base Constructor explicitly by name.

In the header file define a base class:

class BaseClass {
public:
BaseClass(params);
};

Then define a derived class as inheriting the BaseClass:

class DerivedClass : public BaseClass {
public:
DerivedClass(params);
};

In the source file define the BaseClass constructor:

BaseClass::BaseClass(params)
{
//Perform BaseClass initialization
}

By default the derived constructor only calls the default base constructor with no parameters; so in this example, the base class constructor is NOT called automatically when the derived constructor is called, but it can be achieved simply by adding the base class constructor syntax after a colon (:). Define a derived constructor that automatically calls its base constructor:

DerivedClass::DerivedClass(params) : BaseClass(params)
{
//This occurs AFTER BaseClass(params) is called first and can
//perform additional initialization for the derived class
}

The BaseClass constructor is called BEFORE the DerivedClass constructor, and the same/different parameters params may be forwarded to the base class if desired. This can be nested for deeper derived classes. The derived constructor must call EXACTLY ONE base constructor. The destructors are AUTOMATICALLY called in the REVERSE order that the constructors were called.

EDIT: There is an exception to this rule if you are inheriting from any virtual classes, typically to achieve multiple inheritance or diamond inheritance. Then you MUST explicitly call the base constructors of all virtual base classes and pass the parameters explicitly, otherwise it will only call their default constructors without any parameters. See: virtual inheritance - skipping constructors