- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
来自 Bjarne Stroustrup 的 C++ 编程语言第 4 版:
3.3.4。抑制操作
对层次结构中的类使用默认复制或移动通常是一场灾难:只给出一个指向基的指针,我们根本不知道派生的成员是什么类有(§3.2.2),所以我们不知道如何复制它们。所以,最好的办法通常做的是删除默认的复制和移动操作,即消除这两个操作的默认定义:
class Shape {
public:
Shape(const Shape&) =delete; // no copy operations
Shape& operator=(const Shape&) =delete;
Shape(Shape&&) =delete; // no move operations
Shape& operator=(Shape&&) =delete;
~Shape();
// ...
};
为了理解他的意思,我创建了以下示例:
#include <iostream>
using namespace std;
class Person {
private:
int age;
public:
Person(const int& Age) : age {Age} {};
Person(const Person& from) : age {from.Age()} { cout << "copy constructor" << endl; };
Person& operator=(const Person& from) { cout << "copy assignment" << endl; age = from.Age(); return *this; }
virtual void Print() { cout << age << endl; };
void Age(const int& Age) { age = Age; };
int Age() const { return age; };
};
class Woman : public Person {
private:
int hotness;
public:
Woman(const int& Age, const int& Hotness) : Person(Age), hotness {Hotness} {};
Woman(const Woman& from) : Person(from), hotness {from.Hotness()} { cout << "copy constructor of woman" << endl; };
Woman& operator=(const Woman& from) { Person::operator=(from); cout << "copy assignment of woman" << endl; hotness = from.Hotness(); return *this; };
void Print() override { cout << Age() << " and " << hotness << endl; };
int Hotness() const { return hotness; };
};
int main() {
Woman w(24, 10);
Person p = w;
p.Print();
return 0;
}
这个版本程序的输出是:
copy constructor
24
作为菜鸟,这对我来说有点意外,但后来我意识到,因为 p 不是指针,所以没有使用虚拟表,而且因为它是一个人,Person::Print() 被调用了.所以我知道 Person 的复制构造函数被调用了,但我不知道 Woman 的复制构造函数是否被调用了,但这并不重要,因为 p 是一个 Person,通过它我永远无法访问对女人::性感,即使我尝试了类型转换也不行。
所以我认为他可能只是在谈论指针,所以我尝试了这个:
int main() {
Woman w(24, 10);
Person* p = new Person(20);
p->Print();
p = &w;
p->Print();
return 0;
}
新的输出是:
20
24 and 10
现在 p 是一个指针,因为它是一个指针,所以不会进行复制或移动,只会更改引用。
然后我想我可以尝试取消引用 p 并将 w 分配给它:
int main() {
Woman w(24, 10);
Person* p = new Person(20);
p->Print();
*p = w;
p->Print();
return 0;
}
输出是这样的:
20
copy assignment
24
我认为对 p->Print() 的第二次调用会调用 Woman::Print(),因为 p 指向一个 Woman,但事实并非如此。知道为什么吗?来自 Person 的复制任务被调用了,我想是因为 p 是一个 Person*。
然后我试了一下:
int main() {
Woman w(24, 10);
Person* p = new Woman(20, 7);
p->Print();
*p = w;
p->Print();
return 0;
}
新的输出是这样的:
20 and 7
copy assignment
24 and 7
所以我猜因为 p 是 Person* Person 的复制分配被调用,而不是 Woman 的复制分配。奇怪的是,年龄更新了,但热度值保持不变,我不知道为什么。
再试一次:
int main() {
Woman w(24, 10);
Woman* p = new Woman(20, 7);
p->Print();
*p = w;
p->Print();
return 0;
}
输出:
20 and 7
copy assignment
copy assignment of woman
24 and 10
现在数字似乎是正确的。
我的下一步是删除对 Person 的复制赋值的实现,看看是否会调用默认值:
//Person& operator=(const Person& from) { cout << "copy assignment" << endl; age = from.Age(); return *this; }
输出:
20 and 7
copy assignment of woman
24 and 10
请注意,年龄被复制了,所以不用担心。
下一个明显的举措是删除 Woman 的复制分配的实现,看看会发生什么:
//Woman& operator=(const Woman& from) { Person::operator=(from); cout << "copy assignment of woman" << endl; hotness = from.Hotness(); return *this; };
输出:
20 and 7
24 and 10
一切似乎都很好。
所以此时我不太明白作者的意思,所以如果有人能帮助我,我将不胜感激。
谢谢。
密件抄送。
最佳答案
Woman w(24, 10);
Person p = w;
p.Print();
24
Which was a bit of a surprise for me, being a noob, but then a realized that since p is not a pointer, the virtual table is not used, and since it's a Person, Person::Print() got called.
正确
So I knew that the copy constructor for Person got called, but I couldn't know if the copy constructor for Woman got called,...
不,它没有。
...but that wouldn't really matter, since p is a Person, and through it I'd never have access to Woman::Hotness, not even if I tried a cast.
考虑 Person p =
行创建了一个新变量 p
,它具有足够的内存字节来存储 Person
的数据。如果您调用复制构造函数 Person::Person(const Person&);
代码只知道 Person 的数据成员 - 而不是任何派生类型的数据成员 - 所以“切片” Woman
对象复制构成 Person
的数据成员。没有地方放hotness
,也没有被复制。
Person* p = new Person(20);
p->Print();
*p = w;
p->Print();
20
copy assignment
24I thought the second call to p->Print() would call Woman::Print() since p was pointing to a Woman, but it didn't. Any idea why? The copy assignment from Person got called, I think because p is a Person*.
*p
指的是您刚刚分配的 Person
对象。 new
仅被告知有关 Person
- 它无法知道您可能想要/期望/希望有额外的空间来放置 Woman 的额外字段
稍后可以复制,因此它只是为 Person
分配了空间。当您编写 *p = w;
时,它仅复制属于 Person
的字段,使用 Person::operator=(const Person&)
功能。这不会设置指向虚拟调度表的指针来寻址Woman
的表...同样没有Woman
的知识...这就是为什么即使是 >像
函数以后不会被解析为 Print
这样的虚拟Woman::Print
。
Person* p = new Woman(20, 7);
p->Print();
*p = w;
p->Print();
20 and 7
copy assignment
24 and 7So I guess because
p
isPerson*
the copy assignment for Person got called, but not the one for Woman. Weirdly enough, the age got updated but the value of hotness remained the same, and I have no idea why.
这里,虽然 p
确实指向一个 Woman
和 hotness
的额外数据成员,但复制仍然使用 完成Person::operator=
,所以它不知道把额外的字段复制过来。有趣的是,它确实将内部指针复制到虚拟调度表,因此当您使用 p->Print()
时,它会调度到 Woman::Print
。
Woman* p = new Woman(20, 7);
p->Print();
*p = w;
p->Print();
20 and 7
copy assignment
copy assignment of woman
24 and 10Now the numbers seem to be right.
是的,因为编译器知道分配和复制Woman
的所有数据成员,其中包括指向虚拟调度表和hotness
的指针。
您的其余实验(删除显式定义的赋值运算符)表明,哪些成员被复制以及虚拟调度表指针是否/如何更新的问题是涉及的静态类型的基础,因此这些问题是有或没有你的实现。
So at this point I can't quite understand what the author meant to say, so if anyone could help me out, I'd appreciate it.
他的意思是,如果有人认为他们正在获取一个指针或对 Person
的引用并照原样复制它(就像您之前的尝试一样),他们通常会不小心删除派生类(Woman
) 相关成员并以一个简单的 Person
对象结束,在应用程序逻辑级别,Woman
是有意义的。通过删除这些运算符,编译器将防止这种意外的切片构造。正确的做法是提供一个 clone()
函数来创建一个新对象,无论动态对象类型是什么,允许一种“虚拟拷贝”。如果您搜索“克隆”,您会找到很多解释和示例。
关于C++ 为什么我应该抑制默认的复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22468067/
我收到警告 Circular dependency detected! 在 Angular 6 中,我知道为什么会出现这个问题,但这根本不是问题。 我目前正在使用 SVG,按照我的逻辑,我会防止可能出
我试图抑制 clang/gcc 中地址清理程序发出的警告 我的源文件如下所示: int foo(){ double bar[] = {7,8}; return bar[3]; } int ma
我在微服务架构中有一个应用程序。该应用程序从不同的源获取数据,并且从其他各种应用程序获得许多不同的错误响应。某些异常(例如404-Not Found异常)可以引发并返回给最终用户,但其他异常(错误请求
我喜欢使用 readxl包裹。但是,我一直将它用作 RMarkdown 文档和一些 read_excel() 文档的一部分。读入文件时的消息在进行分析时很有用,但在尝试呈现分析时则不然。所以问题是,在
当我编译 JAXB 模式时,生成的类用通用 Javadoc 注释进行修饰。 是否有可能以某种方式抑制生成这些评论? 最佳答案 Annotation to disable JavaDocs Not if
我正在尝试运行专为 Vuze 设计的插件使用Java。为此,我使用这样的命令: /home/x/jre1.6.0_14/bin/java -Dazureus.config.path=/home/x/p
所以 - 我正在使用库 pyminizip - 这是我发现创建受密码保护的 zip 文件的唯一方法。当我使用它时,我收到一个弃用警告:“#”格式需要 PY_SSIZE_T_CLEAN。 现在,我无法控
这个问题在这里已经有了答案: Is ticklabel_format broken? (1 个回答) 关闭 2 年前。 我是 geopandas 的新手,我正在尝试用常规记数法而非科学记数法绘制带有
我从 Valgrind 得到以下日志: MPK ==5263== 4 bytes in 1 blocks are still reachable in loss record 1 of 84 ==52
有什么方法可以抑制 mediawiki 中的贬低警告吗?例如我在个人 wiki 站点的某些页面顶部收到此消息。 Deprecated: Use of MWNamespace::getSubject w
我正在使用 ScheduledThreadPoolExecutor 执行定期任务。 执行必须是周期性的,而不是固定的延迟。 我遇到了以下问题:考虑一个任务的时间为 1 分钟。如果任务需要 5 分钟才能
我是使用 RScaLAPACK 的 R 新手,每次我生成一个新的进程网格时,我都会收到一条消息。 > sla.gridInit(2) [1] "RScaLAPACK:Process Grid Init
我目前正在使用包 readr 读取文件.这个想法是使用 read_delim逐行读取以查找非结构化数据文件中的最大列数。代码输出有 parsing问题。我知道这些并将在导入后处理列类型。有没有办法关闭
所以我试图防止 fatal error 阻止我的脚本运行 所以我将错误报告设置为0: error_reporting(0); 然后我添加了一些垃圾代码.. junk code~~~~trolololo
在使用 summary() 函数(例如,stata 中的 absorb() 函数的等价物)时,是否有一种方法可以抑制线性模型中固定效应的系数。例如,我希望汇总函数只输出截距和 x,而不是因子的系数和标
如何抑制 SBT 的调试消息?它们被记录到标准输出,所以运行一个项目会产生这个: $ cat src/main/scala/Hello.scala object Hello { def main(
有没有办法抑制 Doxygen 对特定文件发出“未记录”警告?我的项目有几个自动生成的代码头,导致它抛出成百上千的错误,难以筛选。 最佳答案 如 documentation 中所述,有一个配置选项。
R的eHOF包中的HOF函数会自动生成进度条。函数中没有关闭进度条的参数。 有什么办法可以抑制函数外的进度条的生成? (我正在应用该功能数百次,目前进度条除了淹没我的屏幕外没有任何作用。) 最佳答案
随着所有 SDK 的出现,能够方便地针对多个 SDK 和平台进行构建。然而,从 3.2 跳到 3.0,甚至偶尔跳到 2.x,我经常收到涉及已更改或被取代的方法的弃用警告: warning: 'UIKe
我创建了一个 PowerShell 脚本,该脚本将为 Cisco Meraki 添加 VPN 连接。 脚本本身按预期运行,但如果发生错误,则会出现“已完成”弹出窗口,并在 PS 窗口中显示错误消息。
我是一名优秀的程序员,十分优秀!