为什么C++不允许向类添加新方法?
Why doesn't C++ allow adding new methods to classes?
这似乎是一个相当任意的限制。正则方法不是就像C函数一样,有一个指向实例的参数吗?
如果是这样的话,我不明白为什么添加新方法会迫使我重新编译类的其余部分。为什么不允许通过单独的修正标题和单独的修正实现来添加方法呢。
考虑这个例子
// in some header
struct X
{
float func(float);
};
// and in another source file
void caller()
{
X x;
std::cout << x.func(2); // will call X:func(float)
}
现在假设我们决定添加一个接受int
的func()
的新版本。
// in some header
struct X
{
float func(float);
void func(int);
};
// and in another source file
void caller()
{
X x;
std::cout << x.func(2);
}
如果caller()
函数没有重新编译,就无法注册它正在调用的函数已经更改——它将在构建中继续调用X::func(float)
。
然后,可能是几个月后(在大型系统中,可能是几年后),另一个开发人员对caller()
同一源文件中的一个函数进行了完全无关的更改。因此,源文件被重新生成。。。最后突然,那个人发现caller()
不会编译——错误消息与他或她正在实现的代码的更改无关。
所有这些都发生在罪犯——引入新成员函数但没有触发重新编译和重建的程序员——不见踪影的时候。
留下来的开发人员要解决这个烂摊子。由于没有关于问题实际原因的信息,也没有关于为什么它昨天有效而今天无效的信息,没有关于如何正确解决问题的真正线索。。。。但仍然是要负责任的人。
这只是C++中的"任意限制"将防止的许多问题之一。
我想到了几件事。一方面,你需要声明方法的范围,我想这就是为什么你可以按照你建议的方式添加新运算符的原因。
另一方面,您在继承方面存在问题。编译器需要知道所有的虚拟方法才能将它们包含在vtable中。
正如deviationfan所说,这并不是真正的问题(假设你想添加一个常规(非虚拟)方法)。
$ for file in X.hh X.cc X-1.hh X-1.cc main.cc; do echo -e "n//--------------//$file"; cat "$file"; done
//--------------//X.hh
//X.hh
struct X {
int foo(int);
};
//--------------//X.cc
//X.cc (available as X.o)
#include "X.hh"
int X::foo(int a){ return a+1; }
//--------------//X-1.hh
//X-1.hh
//copy X.hh and amend it
struct X {
int foo(int);
int bar(int);
};
//--------------//X-1.cc
//X-1.cc
#include "X-1.hh"
int X::bar(int a){ return a+2; }
//--------------//main.cc
//main.cc
#include "X-1.hh"
//^the latest definition
#include <iostream>
int main(){
using namespace std;
X x;
cout << x.foo(1) << endl;
cout << x.bar(1) << endl;
现在是构建部分:
$ make {X,X-1,main}.o
$ g++ {X,X-1,main}.o #links correctly!
$ ./a.out
2
3
即使方法访问类/结构变量也有效。
TL;博士:
如果使用使用跟踪#include
的依赖文件的构建系统,则可以make --assume-old
一个仅通过简单的方法添加(没有重载或虚拟)而更改的头(或touch --date='10 minutes ago' changed_header.hh
),因为依赖于类实例方法的旧子集的所有旧对象文件都不需要重新编译。
此外,正如AliciaBytes所指出的http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf这基本上允许通过dot语法调用独立函数,所以这基本上相当于重新打开一个类来添加琐碎的函数。
重载函数并不是一个真正的问题,因为你总是#include
一个类的特定表示形式(或者同一个类+一组特定的点语法可映射的独立函数),并且你可以有同一类的不同版本(相当于有一个类加上不同的点句法可映射的自立函数集)。(与虚拟函数不同,因为对象实例中有vtables和vtable指针)。
- vcpkg 添加新库,但找不到
- C++11 迭代向量的新方法?
- 运算符重载 += 添加新对象
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- 堆栈粉碎 在我在代码中添加新变量以及一些操作后C++检测到
- 静态堆栈函数不会 1) 输入第一个元素 2)添加新元素时识别旧元素
- 添加新行时工作代码引发异常.调试技巧?
- 宏如何在Tensorflow中添加新的操作时"REGISTER_OP("ZeroOut")
- 使用 Poco::zip 添加新目录始终给出异常
- UE4 - Visual Studio在我从编辑器添加新的c ++文件后无法打开任何源文件 - UBT_COMPILED
- 编写链接函数的更短/更有效的方法,该函数按字典顺序添加新元素
- G 破碎了?无法在课堂上添加新方法
- 通过添加新方法来发展类
- 重新编译二进制类或派生类,以便在基类中添加新方法
- 添加新的继承"interface"和虚拟方法需要重新编译
- 接口更改:为抽象c++方法添加新参数
- 在unordered_map中添加新对象的最佳方法
- 为什么C++不允许向类添加新方法?
- 向 Cocos2d-x SimpleAudioEngine 添加新方法
- 向链表添加新节点的新方法