Calling the Constructor for the Abstract Base clas

2019-07-25 06:06发布

问题:

I know that the if I have an abstract class then I cannot create an object of abstract class type. But Suppose "Base" is a base class and "Derived" is a derived class. In base class I have one member variable name.

Base.h
Base(string name = "");

Base.cpp
Base(string theName){name = theName);

Isn't this creating an object ??

In the Derived class I have member variable age. Now in the derived class default constructor

Derived.h
Derived(string name = "", int theAge = 0);

Derived.cpp
Derived(string theName, int theAge):Base(theName) { age = theAge }

Isn't that also calling the default constructor for the Base ?? So, am I allowed to call a parametrized constructor but not the default one ?

One more thing, if I have another function in the Base class other than the pure function, how can I call that function if I am not allowed to create an object for the Base class ?

Thanks in advance!

回答1:

I know that the if I have an abstract class then I cannot create an object of abstract class type.

With one exception: An object of an abstract class can be created as a subobject of a derived-class object.

In fact, it must be created in that situation, because that's just how inheritance works in C++. An object of a derived class contains an object of the base class (or generally, objects of the base classes, because let us not forget that C++ also supports multiple inheritance).

The standard says this very clearly in §10.4/1:

An abstract class is a class that can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class derived from it.

There you have it: instances of abstract classes may exist within this restriction. Therefore,

Base(string theName){name = theName);

Isn't this creating an object ??

It is a constructor like any other; it is used to create an object. The fact that the class is abstract doesn't matter, given the rule above.

Derived(string theName, int theAge):Base(theName) { age = theAge }

Isn't that also calling the default constructor for the Base ??

Yes, it is.

So, am I allowed to call a parametrized constructor but not the default one ?

A constructor in which all arguments are defaulted is a default constructor.

One more thing, if I have another function in the Base class other than the pure function, how can I call that function if I am not allowed to create an object for the Base class ?

If it's a public function, then anyone who has a derived-class object can call it (this includes the derived class itself). Additionally, anyone who accesses the derived-class object via a pointer or reference to the base class can call it. And of course, the base class itself can call it, too.

If it's a protected function, then the derived class and potential further derived classes can call it.

If it's private, then the base class itself can call it.

As we have established above, you do technically create an object for the base class, as a subobject inside of the derived-class object. So principally, the situation is not special just because the base class is abstract.


The thing to keep in mind here is that the technicalities of the language are defined so that all basic object-oriented features just work as expected. You don't have to worry about these things in your daily programming business.



回答2:

You are conflating two different concepts:

  1. Constructing an object.

  2. Instantiating an object.

An abstract class gets constructed just like any other class. It can have its own custom constructor. Or it can have a default constructor, unless there are certain conditions that disallow default constructors.

An abstract class cannot be instantiated. As you wrote yourself, you "cannot create" an abstract class. You can only create a derived class (unless the derived class is also an abstract class).

Creating a derived class, of course, creates and constructs all of its base classes. Including its base abstract class. Your base class's constructor, the constructor for the abstract class, will be happy to meet its obligation and construct the base abstract class. Following that, the derived class will construct the derived class, and then the entire object would be constructed, and instantiated.



回答3:

Isn't this creating an object ??

No. It just defines how you would construct the object.

Isn't that also calling the default constructor for the Base ?? So, am I allowed to call a parametrized constructor but not the default one ?

Yes it is calling the constructor but like I said above, Base(string theName){name = theName);, doesn't call anything. It just is a constructor definition.

One more thing, if I have another function in the Base class other than the pure function, how can I call that function if I am not allowed to create an object for the Base class ?

You would call it with a pointer/reference to the base class that points/refers to an instance of the derived class.



回答4:

Yup, if you declare constructor like that, then the default one is not generated, because the compiler won't be able to distinguish which one you want to call. This code, for instance, won't be compiled, as CL1(std::string) is private, and default CL1() does not exist.

#include <iostream>
#include<string>
using namespace std;
class CL1{
    CL1(std::string s=""){
        std::cout<<" hello";
    }   
};
int main() {
    CL1 instance;
    return 0;
}