默认构造函数(default constructor)常被用于对象的默认初始化或值初始化。
我的问题是:
如果类没有有意义的初始值,仍需要为类提供默认构造函数吗(不会违反类的不变式 class invariant)?
如果不提供默认构造函数,有什么坏的影响?
例如,一个人必须有名字,空字符串并不是一个有意义的名字。
提供默认构造函数:
#include <string>
class Person {
public:
Person() : name("") {} // 会导致类的对象存在无效状态
explicit Person(const std::string &n) : name(n) {}
private:
std::string name;
};
不提供默认构造函数:
#include <string>
class Person {
public:
explicit Person(const std::string &n) : name(n) {}
private:
std::string name;
};
补充
非常感谢回答问题的各位,但是感觉没有人回答到点上。这个问题是一个关于类的设计的问题,而不是技术上的问题。
怪我咯2017-04-17 13:27:04
The constructor of the class will automatically call the default constructor of the member. If you can accept this behavior, you don’t need to call it manually.
For example, in your code, not writing name("")
is actually equivalent to name()
.
I usually only initialize members that do not have a default constructor, and do not initialize others, except for special ones.
大家讲道理2017-04-17 13:27:04
Generally provide a default constructor if you want to use your class like this:
Person persons[100];
std::list<Person> persons(100);
// 这里两行都会报错,因为没有默认构造函数。。。
// 以及很多STL容器、算法都要求,被使用类有默认构造函数
This is just one aspect. Let’s take a look at "effective C++" and "more effective C++"! These two books are more thorough.
迷茫2017-04-17 13:27:04
For build-in types, the compiler will provide a default constructor if you do not initialize it explicitly.
For details, you can read "In-depth exploration of the c++ object model".
ringa_lee2017-04-17 13:27:04
Your problem is not whether to provide a default constructor. There is no real difference between the default constructor you provide and the system's default constructor.
What you are struggling with is that the parameterless constructor actually generates an object with an invalid initial state.
1. In many cases, this temporary invalid state has no impact, and other functions need to be called for initialization.
2. You can also define a default constructor, but declare it as private, and the world will be clean.
I personally recommend option 1. I think that there are many reasons why an object may be in an incorrect state (for example, the object holds a network connection, or the object needs to perform account and password authorization operations. You cannot do all the work. Put them all in the constructor). It is only necessary to judge the status during relevant corresponding operations.