如果赋值运算符设为私有,为什么仍允许此赋值?
Why is this assignment still allowed if the assignment operator is made private?
给定这个例子:
// 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_;
};
我希望在 B 中大约void setA(A* a) { a_ = *a; }
时引发错误,因为 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();
}
我还可以确认,对于正常方法,我得到了预期的错误。将 B 中的void func();
更改为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) 和树尖确认了所有这些行为,反对-std=c++98
-std=c++17
.
类模板的非虚拟成员函数(如示例中的setA
)不会实例化,除非实际使用。
我的问题是为什么允许这样做?
其实不然。
但是,由于您从未实际实例化模板B<T>::setA()
,因此代码尚未"完成编译"。
我发现这很难相信,因为我没有使用优化进行编译
这与优化无关。
当我使用模板化 B 时,我仍然无法重现错误。
您需要致电setA()
。
您可能会认为这是替换失败不是错误的扩展;我将称之为不使用损坏的模板的事情不是错误。或简称NUTBTTINAE。:)
另请参阅:为某些不可复制或可移动的T
实例化std::vector<T>
,并观察它是否有效,直到您尝试将内容推入其中。
相关文章:
- 为"adjacent"变量赋值时出现问题
- C++中的赋值发生,尽管右侧出现异常
- 用C++中的sscanf赋值
- 为std::string的某个索引赋值
- 重载Singly Linked List中的赋值运算符
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- gtest_使用setargpointee在函数中赋值
- 非常量变量只读位置的赋值
- 当我尝试构建此程序时,出现此错误:需要左键作为赋值的左操作数
- 如果赋值运算符设为私有,为什么仍允许此赋值?
- 我很难为 if/else 语句编写此赋值的代码.这是第一堂编程课
- 为什么我需要在用户为其赋值之前初始化此变量
- 如何在不重载赋值运算符的情况下运行此代码
- 此指针赋值应生成段错误
- 关于此左值的错误,此左值需要作为赋值的左操作数
- 为什么此赋值操作会导致不明确的函数调用
- 将此指针赋值给指针的右值引用
- 在显式析构函数调用后,此赋值是否无效
- 如何更正此程序中的重载赋值
- 此变量赋值有何不同?