数据成员是一个类对象的引用还要调用构造函数吗
class a{}
class c{ a &p;}//构造函数已经省略
int main ()
{
a pp;
c j(pp);//这里是否要调用a的构造函数
}
我对 C++中 拷贝构造函数 以值传递的方式 给函数参数传值 的理解
还有,为什么是值传递呢?
要看懂本文章你需要了解:
注意:请按照编号顺序查看代码说明,请从下往上看
class Person
{
public:
Person()
{
cout << "默认构造函数调用" << endl;
}
Person(int age)
{
m_Age = age;
cout << "有参构造函数调用" << endl;
}
—————————————————————————————————————————————————————————————————————————————————————————————
// 8.因为doWork传入的参数是p1,所以会自动调用拷贝构造函数
// p1将会以引用的方式传入拷贝构造函数。
// 所以,当编译器发现是引用,会自动转化 const Person& p 为 const int* const p = &p1
// 注意,这里的p1是只读的,因为被const修饰了,不可修改,p1的作用域也只限于拷贝构造函数内。
Person(const Person& p)
{
// 9.注意,拷贝构造函数是以引用作为它的参数,其实在这个函数内还是可以修改实参的
//p.m_Age = 12; 因为拷贝构造函数使用了引用,所以去掉const就可以更改实参了
// 10.我们知道构造函数的一个目的是进行初始化操作
// 我们将m_Age初始化,在这里,我们就算实现了所谓的值传递
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person001()
{
cout << "析构函数调用" << endl;
}
int m_Age;
};
// 7.这里相当于写了 Person p = p1;
// 使用了隐式转换法来调用 (调用的方法有3种,括号法、显示法、隐式转换法,请自行去了解)
// 创建对象的时候,构造函数会自动调用,而且只调用一次。
// 因为传入的参数是p1所以,会自动调用拷贝构造构造函数
void doWork(Person p) //这里会自动调用拷贝构造函数
{
// 11.好,回到这里
// p.m_Age原本等于10,我们现在尝试修改p.m_Age为12,看看能不能改变实参
p.m_Age = 12;
}
void test()
{
// 3.实例化对象p1,运行这行代码时会调用“默认构造函数”,然后在text()函数销毁前执行“析构函数”
Person p1;
// 4.给p1中的m_Age赋值为10
p1.m_Age = 10;
// 5.屏幕显示:Person age = 10
cout << "Person age = " << p1.m_Age << endl;
// 6.p1做为参数传入doWork函数,注意这里是值传递(那为什么呢?)
doWork(p1);
// 12.并不能改变实参,所以我们可以知道,拷贝构造函数 以值传递的方式 给函数参数 传值
cout << "Person age = " << p1.m_Age << endl;
}
// 1.首先看这里,这里是主函数,程序的开始
int main()
{
// 2.调用test函数
test();
system("pause");
return 0;
}
如果文章有错误,欢迎指正:2892870137@qq.com
欢迎拜访我的主博客:https://h-james.github.io/
优化问题标题: 类对象引用的数据成员是否需要调用构造函数,实例化基类的两个派生类时是否需要调用两次构造函数?
答案: 1. 当一个类对象是通过引用作为数据成员时,引用本身不需要调用构造函数。引用是一个别名,它引用的对象已经在其他地方进行了实例化和初始化,所以不需要再调用构造函数。
class Base {
public:
Base() {
// 基类的构造函数
cout << "Base constructor" << endl;
}
// ...
};
class Derived1 : public Base {
public:
Derived1() {
// 派生类1的构造函数
cout << "Derived1 constructor" << endl;
}
// ...
};
class Derived2 : public Base {
public:
Derived2() {
// 派生类2的构造函数
cout << "Derived2 constructor" << endl;
}
// ...
};
int main() {
Derived1 d1; // 需要调用一次基类的构造函数
Derived2 d2; // 需要再次调用一次基类的构造函数
return 0;
}
运行以上代码,可以看到输出结果为:
Base constructor
Derived1 constructor
Base constructor
Derived2 constructor
这说明在实例化派生类时,首先调用基类的构造函数初始化基类部分的成员,然后再调用派生类自己的构造函数初始化派生类部分的成员。所以,实例化两个派生类需要调用两次基类的构造函数。