在我的项目中,我有彼此关联的类。如果一个类具有另一个类的对象作为属性,那么在编写构造函数时如何进行初始化?
我尝试如下编写,但出现错误。请注意,类Date具有一个构造函数,该构造函数为Date()。如果我将dueDate = 0写入,它将给出一个错误。
也可以在Task(string n,Date d)中初始化其他属性或仅初始化参数吗?
class Task
{
private:
int id;
string name;
Date dueDate;
string status;
bool urgent;
public:
Task();
Task(string n, Date d);
};
Task::Task(){
id = 0;
name = "*";
dueDate = 0;
status = "New";
urgent = false;
}
Task::Task(string n, Date d){
name = n;
dueDate = d;
}
答案 0 :(得分:3)
假设Date
为int
提供了一个构造函数,那么这里的正确解决方案是切换到member initializer lists而不是在构造函数的主体中 assigning 表示成员均已默认初始化,然后重新分配)。只需将所有分配移至初始化,如下所示:
Task::Task() : id(0), name("*"), dueDate(0), status("New"), urgent(false) {}
Task::Task(string n, Date d) : name(std::move(n)), dueDate(std::move(d)) {}
这会将您的用例更改为只需要Date
的构造器(显式或其他)即可接受int
(或指针,其中0
将被解释为{{1 }}指针),而不需要处理从NULL
到现有实例的分配。
以这种方式进行操作还更加高效;而不是五种默认构造和五种重新分配,您只需使用一开始的预期参数进行五种直接构造。在构造函数接受0
和string
的情况下,使用Date
意味着对象仅从头开始构造一次(当调用者调用构造函数时),然后使用move-construction掏空参数并将其内部移动到数据成员,而不是复制构造只是为了扔掉源。
如果必须分配给现有的std::move
,并且它不能为您隐式转换Date
,如果您有int
的移动或复制分配运算符,则可以重用它。在这种情况下,对代码的最小修复就是替换:
Date
具有:
dueDate = 0;
但是,再次使用初始化列表是这里的方法。
注意:如果dueDate = Date(0); // Explicitly construct a `Date` then copy/move assign to dueDate
的唯一构造函数不带参数,如您的示例:
Date
如果只希望它具有默认值,则无需显式初始化或分配它。在执行包含数据成员的类的构造函数主体之前,将使用其默认构造函数自动初始化数据成员。 Date::Date()
{
day = 0;
month = 0;
}
自动发生。在这种情况下,Date()
会变得毫无意义,因为当它已经为空{>时,它将dueDate = Date();
重新分配给一个新的空dueDate
}。
答案 1 :(得分:0)
您有两种选择。
首先,创建一个指针:
class Task
{
private:
Date* dueDate;
//...
};
Task::Task(){
// ...
dueDate = new Date(0);
}
Task::~Task(){
// This way requires a destructor though
delete dueDate;
}
选项2:您可以重载赋值运算符:
class Date
{
public:
void operator=(int i);
};
Date::operator=(int i) {
// implement construction
}
然后,在任务中:
Task::Task(){
// ...
dueDate = 0;
}
这是我所知道的两个选项。在C ++中,无法将构造函数直接作为成员变量来调用。您必须将其用作指针或实现赋值运算符。
编辑:向Shadow Ranger大喊大叫,他在评论中指出C ++ 14及更高版本具有不需要析构函数的解决方案:
class Task
{
private:
std::unique_ptr<Date> dueDate;
//...
};
Task::Task(){
// ...
dueDate = std::make_unique<Date>(0);
}
答案 2 :(得分:-2)
class Task
{
private:
int id;
string name;
Date *dueDate;
string status;
bool urgent;
public:
Task();
Task(string n, Date d);
};
Task::Task(){
id = 0;
name = "*";
dueDate = new Date(0);
status = "New";
urgent = false;
}
Task::Task(string n, Date d){
name = n;
dueDate = &d;
}