我正在学习C++,正在从中读取复制构造函数C++: The Complete Reference.书上写着
允许复制构造函数具有其他参数,只要它们具有为其定义的默认参数即可.但是,在所有情况下,第一个参数必须是对执行初始化的对象的引用.
但我很困惑,我们将如何通过这些额外的参数?我相信应该有一些方法没有在书中给出,我无法弄清楚.谁能帮我吗?
编辑: 也可以在所有三种情况下传递这些额外的参数,即
可能重复:
复制和直接初始化的动机背后的动机是什么?
通过复制初始化,我的意思是这样的:
struct MyStruct
{
MyStruct(int) {}
MyStruct(const MyStruct&) {}
};
MyStruct s = 5; // needs *both* the int and copy constructor
Run Code Online (Sandbox Code Playgroud)
尽管用C++编程多年,但我从未意识到上面的代码需要复制构造函数(感谢jogojapan).暂时一直被遗忘,因此我甚至都不知道它是否存在(至少在肤浅的层面,尽管它被优化了),直到它被指出给我.
经过大量的谷歌搜索,我了解它是如何工作的.我的问题是为什么它是这样的?
为什么标准不能使上面的例子不需要复制构造函数?是否有一些特定的案例/示例表明在这种初始化中需要复制构造函数很重要?
如果没有合理的解释为什么事情就是他们的方式,我只是把它看作是一件讨厌的神器,但如果有一些重要的东西我不想知道,我宁可不要无知.
我有一个基类和两个派生类,我需要将一个指向派生类对象的指针复制到另一个类中,就像示例一样.
class Base
{
public:
Base(const Base& other);
}
class Derived1 :public Base
{
public:
Derived1(const Derived& other): Base(other){...};
}
class Derived2: public Base
{
public:
Derived2(const Derived& other): Base(other){...};
}
main()
{
Derived 1 d1;
Derived2 d2(d1)
}
Run Code Online (Sandbox Code Playgroud)
我尝试从Derived 1 ti base(允许向上转换)传递,然后到*dynamic_cast*Base到Derived2并调用复制构造函数,但它不起作用.我只需要在两个派生对象之间复制两个对象的Base部分.
我有一个公开继承的课程QWidget:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(const MyWidget& other)
:
obj1(other.obj1),
obj2(other.obj2)
private:
some_class obj1;
some_class obj2;
};
Run Code Online (Sandbox Code Playgroud)
当我构建我的项目时,编译器抱怨:
警告::基类"类QWidget"应该在复制构造函数中显式初始化.
我从stackoverflow上的其他问题中检出了,得到了我的答案.但事实是,当我添加这样的初始化时:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(const MyWidget& other)
:
QWidget(other), //I added the missing initialization of Base class
obj1(other.obj1),
obj2(other.obj2)
private:
some_class obj1;
some_class obj2;
};
Run Code Online (Sandbox Code Playgroud)
我收到编译错误:
QWidget :: QWidget(const QWidget&)在此上下文中是私有的
所以,请解释一下我做错了什么.
真实的例子显然要长得多,但这总结了我的问题:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Object(int param1);
Object::Object(int param1, int param2);
};
Object::Object(){}
Object::Object(int param1):mInt1(param1){}
Object::Object(int param1, int param2):mInt1(param1),mInt1(param2){}
Run Code Online (Sandbox Code Playgroud)
然后在主要:
if (type1){
Object instance(param1);
}
else{
Object instance(param1,param2);
}
// do stuff with instance
Run Code Online (Sandbox Code Playgroud)
哎呦!这不起作用,实例超出了后续程序的范围.
Object instance;
if (type1){
instance = Object(param1);
}
else{
instance = Object(param1,param2);
}
// do stuff with instance
Run Code Online (Sandbox Code Playgroud)
但是现在我遇到了麻烦,因为我没有定义复制构造函数.我真的不想写一个拷贝构造函数,因为我的实际类有几十个成员,其中许多是非基本类型,可能需要更多的工作来复制.
具体来说,我得到了
main.cpp: error: use of deleted function ‘Object& Object::operator=(Object&&)’
instance = Object(param1);
^
note: ‘Object& Object::operator=(Object&&)’ is implicitly deleted because the default definition would …Run Code Online (Sandbox Code Playgroud) 当类显式声明复制操作(即复制构造函数或复制赋值运算符)时,不会为该类声明移动操作.但是当一个类显式声明一个移动操作时,复制操作被声明为已删除.为什么存在这种不对称?为什么不指定如果声明移动操作,则不会声明复制操作?据我所知,不存在任何行为差异,也不需要对移动和复制操作进行不对称处理.
[对于喜欢引用该标准的人,在12.8/9和12.8/20中指定缺少具有复制操作声明的类的移动操作声明,并且具有移动操作声明的类的已删除复制操作在12.8 /中指定7和12.8/18.]
考虑以下最小的工作示例:
#include <atomic>
int main() {
::std::atomic<bool> a = false;
}
Run Code Online (Sandbox Code Playgroud)
复制ctor和原子的复制分配都被明确删除.但是,这应该调用ctor完全是一个bool.
g ++和clang ++都抱怨此行试图调用以下内容的副本atomic:
$ g++ -std=c++1z a.cpp
a.cpp: In function ‘int main()’:
a.cpp:4:27: error: use of deleted function ‘std::atomic<bool>::atomic(const std::atomic<bool>&)’
::std::atomic<bool> a = false;
^~~~~
$ clang++ -std=c++1z a.cpp
a.cpp:4:23: error: copying variable of type '::std::atomic<bool>' invokes deleted constructor
::std::atomic<bool> a = false;
^ ~~~~~
Run Code Online (Sandbox Code Playgroud)
他们为什么要复制atomic?
我有一个类,复制构造函数和构造函数采用std::reference_wrapper:
#include <functional>
#include <iostream>
class Class {
public:
Class() {
std::cout << "Class()" << std::endl;
}
Class(Class const &) {
std::cout << "Class(Class const &)" << std::endl;
}
Class(std::reference_wrapper<Class>) {
std::cout << "Class(std::reference_wrapper<Class>)" << std::endl;
}
Class(std::reference_wrapper<const Class>) {
std::cout << "Class(std::reference_wrapper<const Class>)" << std::endl;
}
};
int main() {
Class a;
Class b = a;
Class c = std::ref(a);
Class d = std::cref(a);
}
Run Code Online (Sandbox Code Playgroud)
当正常编译时(g++ --std=c++17 test.cpp),它按照需要工作,按顺序调用四个构造函数:
$ ./a.exe
Class()
Class(Class const &)
Class(std::reference_wrapper<Class>) …Run Code Online (Sandbox Code Playgroud) #include<iostream>
using namespace std;
class A
{
public:
A(){ cout <<"1";}
A(const A &obj){cout <<"2";}
};
class B: virtual A
{
public:
B(){cout <<"3";}
B(const B & obj):A(obj){cout<<"4";}
};
class C: virtual A
{
public:
C(){cout<<"5";}
C(const C & obj):A(obj){cout <<"6";}
};
class D:B,C
{
public:
D(){cout<<"7";}
D(const D & obj):C(obj),B(obj){cout <<"8";}
};
int main()
{
D d1;
D d(d1);
}
Run Code Online (Sandbox Code Playgroud)
我得到 13571468 作为输出。但我认为输出应该是 13572468。为什么运行普通构造函数而不是类 A 的复制构造函数?
c++ inheritance constructor copy-constructor virtual-inheritance
c++ ×10
copy-constructor ×10
c++11 ×2
inheritance ×2
atomic ×1
constructor ×1
gcc-pedantic ×1
qt ×1
scope ×1