英文:
Call constructor with different argument types from another constructor in C++17
问题
I have a class called Date:
class Date {
public:
explicit Date(const int day = 1, const int month = 1, const int year = 0) {
this->Construct(day, month, year);
}
explicit Date(const string &date_as_string) {
int day, month, year;
// parsing the string date_as_string
this->Construct(day, month, year);
}
private:
void Construct(const int day, const int month, const int year) {
// constructing the Date object
}
};
有没有一种方法可以直接从Date(string&)调用Date(int, int, int),从而避免编写单独的函数?
UPD:
一些澄清。我的类应该如下所示:
class Date {
public:
explicit Date(const int day = 1, const int month = 1, const int year = 0) {
// constructing the Date object
}
explicit Date(const string &date_as_string) {
int day, month, year;
// 解析字符串 date_as_string
// 调用 Date(day, month, year) 来构造 Date 对象
}
// 其他任何函数
private:
// 私有字段
};
并且以下代码应该编译通过:
Date date("some_string_containing_date");
Date date(1, 1, 0);
英文:
I have a class called Date:
class Date {
public:
explicit Date(const int day = 1, const int month = 1, const int year = 0) {
this->Construct(day, month, year);
}
explicit Date(const string &date_as_string) {
int day, month, year;
// parsing the string date_as_string
this->Construct(day, month, year);
}
private:
void Construct(const int day, const int month, const int year) {
// constructing the Date object
}
};
Is there a way to call Date(int, int, int) directly from Date(string&), thus avoiding writing a separate function?
UPD:
Some clarification. My class should look like:
class Date {
public:
explicit Date(const int day = 1, const int month = 1, const int year = 0) {
// constructing the Date object
}
explicit Date(const string &date_as_string) {
int day, month, year;
// parsing the string date_as_string
// call Date(day, month, year) to construct the Date object
}
// any other functions
private:
// private fields
};
And the following code should compile:
Date date("some_string_containing_date");
Date date(1, 1, 0);
答案1
得分: 3
可以在另一个构造函数的基础上定义一个构造函数。不过,我认为你需要使用一些额外的函数来实现它。
调用同一类的另一个构造函数的构造函数被称为“委托构造函数”,并使用与成员初始化列表相同类型的语法,但使用类自身的名称而不是基类和成员的名称:
ClassName::ClassName(SomeParam1 p1, SomeParam2 p2)
: ClassName(arg_expr1, arg_expr2, arg_expr3)
{ /* 在目标构造函数完成后可以添加任何其他逻辑 */ }
但由于需要中间对象 date_as_struct
,这个情况有点棘手。或者根据更新后的问题,只需在进入另一个构造函数之前进行一些解析。我会通过创建一个接受 Date_as_struct
的额外私有构造函数来解决这个问题:
class Date {
public:
explicit Date(int day = 1, int month = 1, int year = 0);
explicit Date(const string &date_as_string);
/* ... */
private:
struct Date_as_struct {
int day;
int month;
int year;
};
explicit Date(const Date_as_struct&);
static Date_as_struct ParseStringContainingDate(const std::string&);
};
// 对于字符串构造函数,只需这样:
Date::Date(const std::string& date_as_string)
: Date(ParseStringContainingDate(date_as_string))
{}
Date(const Date_as_struct&)
构造函数可以非常容易地委托给 Date(int, int, int)
,或者反之,取决于实际成员初始化的自然方式。
英文:
Yes, you can define one constructor in terms of another. No, I don't think you can do it without some additional function.
A constructor which invokes another constructor of the same class is called a "delegating constructor", and uses the same sort of syntax as a member initializer list, but using the class's own name instead of its base classes and members:
ClassName::ClassName(SomeParam1 p1, SomeParam2 p2)
: ClassName(arg_expr1, arg_expr2, arg_expr3)
{ /* any other logic after the target constructor finishes */ }
But this case is a bit tricky because of the need for the intermediate object date_as_struct
. Or with the updated question, just the need to do some parsing before entering another constructor. I'd solve this one by making an additional private constructor which takes the Date_as_struct
:
class Date {
public:
explicit Date(int day = 1, int month = 1, int year = 0);
explicit Date(const string &date_as_string);
/* ... */
private:
struct Date_as_struct {
int day;
int month;
int year;
};
explicit Date(const Date_as_struct&);
static Date_as_struct ParseStringContainingDate(const std::string&);
};
Date_as_struct
and ParseStringContainingDate
are declared here as private, since it sounds like nothing else will really use them.
Then for the string constructor, you just have
Date::Date(const std::string& date_as_string)
: Date(ParseStringContainingDate(date_as_string))
{}
The Date(const Date_as_struct&)
constructor can very easily delegate to Date(int, int, int)
or vice versa, whichever is more natural for the actual member initialization.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论