使用带或不带初始值设定项列表的默认构造函数作为类数据成员的对象
对于以下程序,
#include <iostream>
using namespace std;
class university{
private:
string uni;
public:
university(){
cout<<"default constructor of university is invoked"<<endl;
}
university(string u){
uni =u;
cout<<"parametrized constructor of university is invoked: "<<uni;
}
};
class student{
private:
university u;
public:
student() {
u = university("ABC");
}
};
int main()
{
student s;
return 0;
}
输出为:
default constructor of university is invoked
parametrized constructor of university is invoked: ABC
但是当更改学生类的构造函数以使用初始化列表时,如下所示:
student(): u(university("ABC")){
}
输出为:
parametrized constructor of university is invoked: ABC
我的问题是: 对于第二种情况,当编译器在student类的私有部分运行行university u
时,它是否创建类'university'的对象'u'并为其分配内存地址,或者对象是否在初始化列表中创建?如果是前者,那么为什么它不调用默认构造函数?
对于第一种情况,我有同样的问题在哪里创建对象并分配内存位置。
for the following program
#include <iostream>
using namespace std;
class university{
private:
string uni;
public:
university(){
cout<<"default constructor of university is invoked"<<endl;
}
university(string u){
uni =u;
cout<<"parametrized constructor of university is invoked: "<<uni;
}
};
class student{
private:
university u;
public:
student() {
u = university("ABC");
}
};
int main()
{
student s;
return 0;
}
the output is:
default constructor of university is invoked
parametrized constructor of university is invoked: ABC
but when changing the the constructor of student class to use initializer list like following:
student(): u(university("ABC")){
}
the output is:
parametrized constructor of university is invoked: ABC
My question is:
for the second case, when the compiler runs the line university u
in the private section of student class, does it create an object 'u' of class 'university' and allocate a memory address to it, or does the object get created in the initializer list? if the former, then why didn't it call the default constructor?
for the first case, I have the same question where does the object get created and assigned a memory location.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
“分配内存”和“分配内存位置”与这里无关。您询问的是如何构造属于另一个类的成员的对象。试图在这里引入内存分配的主题只会让事情变得混乱。高级 C++ 技术允许“在同一位置”重复构造和销毁对象(通过放置 new 和显式析构函数调用)。实际的内存位置和对象构造/销毁完全无关紧要。它们彼此无关,如果您忘记有关内存位置的所有内容,只关注对象构造和销毁的主题,将会很有帮助。话虽如此:
对象构造函数负责构造对象的所有成员。这就是规则。没有例外。句号。
这会起作用,但是这也会在一个令人困惑的成员中实现这一点。这说明了以下事件序列:构造一个临时的大学对象,然后复制构造学生类的实际成员,最后临时对象被销毁。这是没有必要的,只会把水搅浑。使用更简单的现代 C++ 语法,这应该是:
这种更短、直接的语法以一种简单、简洁的方式准确地描述了正在发生的事情:对象的构造函数构造该对象的所有成员,即这里仅构造一个成员。它被称为
u
。u
的构造函数被调用,并将字符串作为参数传递给它。大学的“参数化”构造函数被调用。构造函数的成员初始化部分只不过是一个简单的列表:这里是我的类成员,这里是它们各自构造函数的参数。阿布拉卡达布拉:它们是被建造出来的。如果构造函数没有成员初始化部分,或者没有在初始化部分列出对象的成员,则将调用相应类成员的默认构造函数。
就是这样,这就是它的全部内容:您的类(*此处该类称为
student
)具有成员,并且该类的构造函数显式初始化它们,为类成员调用相应的构造函数。如果任何类成员未在初始化部分中列出,则将调用其默认构造函数,如果类成员没有默认构造函数,则生成的代码格式错误且无法编译。"Allocating memory" and "assigning memory location" has nothing to do with anything here. You are asking about how objects that are members of another class get constructed. Trying to pull in the subject of memory allocation here only confuses things. Advanced C++ techniques allow objects to be repeatedly constructed and destroyed "in the same place" (via placement new and explicit destructor invocations). Actual memory locations, and object constructions/destructions, are completely immaterial. They have nothing to do with each other, and it will be helpful if you simply forget everything about memory locations, and focus only on the topic of object construction and destruction. Having said all of that:
An object constructor is responsible for constructing all members of the object. That's the rule. No exceptions. Full stop.
This will work, but this also does this in a confusing member. This spells out the following sequence of events: a temporary
university
object gets constructed, then copy-constructs the actual member of thestudent
class, finally the temporary object gets destroyed. This is unnecessary and only serves to muddy the waters. Using a simpler, modern C++ syntax, this should be:This shorter, direct syntax, describes exactly what's going on in a simple, concise manner: the object's constructor constructs all members of this object, namely just one, here. It's called
u
.u
's constructor gets invoked passing to it a character string as a parameter. Theuniversity
's "parametrized" constructor gets called. A constructor's member initialization section is nothing more than a simple list: here are my class members, and here are the parameters to their respective constructors. Abracadabra: they're constructed.If a constructor does not have a member initialization section, or does not list the object's member in the initialization section, the corresponding class members' default constructors get called.
That's it, that's all there is to it: your class *here the class is called
student
) has members, and the class's constructor explicitly initializes them, the corresponding constructor gets called, for the class members. If any class member is not listed in the initialization section its default constructor gets called, if the class member does not have a default constructor the resulting code is ill-formed and won't compile.成员未在构造函数主体中初始化。它们在执行构造函数主体之前初始化。当你写:
那么
u = unisversizy("ABC");
不是初始化。由于您没有为u
成员提供初始化程序,因此它将通过调用其默认构造函数来初始化。然后,在构造函数中,university("ABC")
通过调用另一个构造函数来创建另一个对象,并将其分配给u
。PS:在我看来,“参数化构造函数”这个术语是一个非常具有误导性的术语。教程中经常出现的“参数化构造函数”和默认构造函数之间的区别是错误的。默认构造函数是可以不带参数调用的构造函数,因此以下是默认构造函数(并且可以带参数调用):
Members are not initialized in the body of the constructor. They are initialized before the body of the constructor is executed. When you write:
Then
u = unisversizy("ABC");
is not initialization. As you are not providing an initializer for theu
member it will be initialized by calling its default constructor. Then in the constructoruniversity("ABC")
creates another object by calling the other constructor and assigns that tou
.PS: In my opinion the term "parametrized constructor" is a very misleading term. The distinction between "parametrized constructor" and a default constructor that is often made in tutorials is just wrong. A default constructor is a constructor that can be called without parameters, hence the following is a default constructor (and it can be called with parameters):
情况 1
这里我们考虑以下情况:
当您写道:
这些是上述语句的效果:
student
的默认构造函数student::student()
是叫。student::student()
的主体之前,类<的默认构造函数university::university()
code>university 被隐式调用。结果,您得到输出:现在,一旦
university::university()
的主体完全执行,将执行默认 ctorstudent::student() 的主体
已恢复。在执行
student::student()
主体时遇到以下语句:这是一个赋值,而不是初始化。由于表达式
university("ABC")
,使用university参数化构造函数 创建了一个临时
university
对象code>,因此您会得到输出:u
。情况 2
这里我们考虑这样的情况:
当您写道:
发生的情况是这样的:
student
的默认构造函数。student::student()
的主体之前,参数化构造函数university::university(std::调用类
是因为您有表达式university
的 string)university("ABC")
并且数据成员u
是已初始化。请注意,由于调用了参数化 ctor,您将得到输出:student 的默认 ctor
恢复。student::student()
的主体注意
在示例的情况 2 中,您应将
student():u(university("ABC")){}
更改为:Case 1
Here we consider the case where we have:
When you wrote:
These are the effects of the above statement:
student::student()
of classstudent
is called.student::student()
, the default ctoruniversity::university()
of classuniversity
is implicitly called. As a result, you get the output:Now once the body of
university::university()
is completely executed, execution of the body of default ctorstudent::student()
is resumed.While executing the body of
student::student()
the following statement is encountered:which is an assignment and not an initialization. Due to the expression
univerisity("ABC")
, a temporaryuniversity
object is created using the parameterized constructor of classuniversity
and hence you get the output :u
.Case 2
Here we consider the case where we have:
When you wrote:
this is what happens:
student
is called.student::student()
, the parameterized constructoruniversity::university(std::string)
of classuniversity
is called because you have the expressionuniversity("ABC")
and the data memberu
is initialized. Note that since the parameterized ctor was called you get the output:student::student()
of classstudent
resumes.Note
In case 2 of your example, you should change
student():u(university("ABC")){}
to just: