c++ - 如果赋值运算符是私有的,为什么仍然允许这个赋值?
问题描述
给定这个例子:
// test.cpp
class A {
public:
private:
A& operator=(const A&); // don't allow assignment operator
A(const A&); // don't allow default copy constructor
void func();
};
template<class T>
class B {
public:
B(A &a) : a_(a) {}
void setA(A* a) { a_ = *a; } // No error is raised here.
void func();
protected:
B& operator=(const B&) { return *this; }
A& a_;
};
我希望void setA(A* a) { a_ = *a; }
在 B 中引发错误,因为 A 的赋值运算符是私有的,并且 A 和 B 不是朋友,但是当我编译它时不会引发错误。
$ g++ -c test.cpp // My invocation for reference
我的问题是为什么允许这样做?这种行为是否可能根据 c++ 标准得到保证?
我注意到,如果我没有将 B 设为模板类,则会按预期得到错误。
$ g++ -c test.cpp
test.cpp: In member function ‘void B::setA(A*)’:
test.cpp:11:29: error: ‘A& A::operator=(const A&)’ is private within this context
void setA(A* a) { a_ = *a; }
^
test.cpp:4:8: note: declared private here
A& operator=(const A&); // don't allow assignment operator
^~~~~~~~
这让我相信,因为我实际上并没有“使用”模板化的 B,编译器可以简单地“忽略它”并优化它。我发现这很难相信,因为我没有使用优化进行编译,而且当我使用模板 B 时仍然无法重现错误。
// Appending this to test.cpp still doesn't result in an error.
void func(A &alloc) {
B<int> b(alloc);
b.func();
}
我还可以确认,对于正常方法,我得到了我期望的错误。void func();
将B更改为void func() { a_.func(); }
导致:
test.cpp:14:22: error: 'func' is a private member of 'A'
void func() { a_.func(); }
^
test.cpp:6:10: note: declared private here
void func();
^
我已经用 clang++ (v6.0.1)、g++ (v7.4.0) 和树尖 clang 确认了所有这些行为,并-std=c++98
反对-std=c++17
.
解决方案
类模板的非虚拟成员函数 - 就像setA
在您的示例中一样 - 除非并且直到实际使用,否则不会实例化。
推荐阅读
- vba - 将word文件转换为txt文件
- python - Python中的多个随机矩阵
- sql - Knex 查询错误“pollers.description\”必须出现在 GROUP BY 子句中或在聚合函数中使用”
- json - 调用 PowerShell 脚本时出现 Azure 扩展错误
- vb.net - 条件,多行中的两行包含元素
- python - 如何使用类在div之间查找文本
- java - 数数 一个范围内每个数字的设置位,然后将其相加
- docker - 在 docker 镜像中包含子文件夹作为单独的层
- javascript - Babel 正在输出一个节点无法运行的文件,理由是“未定义要求”
- angular - 限制在 agm-map 中的特定国家