在“更有效的C ++”中,提出了一个有趣的观点,即混合数组和多态是一个坏主意。例如:
class Base {
public:
Base(int y) : a(y) {}
int a;
};
class D : public Base {
public:
D(int w, int y) : Base(y), c(w) {}
int c;
};
std::ostream& operator<<(std::ostream& os, const Base &obj )
{
os << obj.a << std::endl;
return os;
}
// This function will work perfectly well if i pass in a `Base` array,
// but if i pass in `D` array we are going to run into some problems.
// Namely that `arr[i+1] = &arr[i] + sizeof(Base)` will not progress
// the array correctly for a `D` array.
void printArray(const Base arr[]) {
for (int i = 0; i < 5; ++i) {
std::cout << arr[i];
}
}
int main() {
D arr[5] = { D(0, 10), D(1, 11), D(2, 12), D(3, 13), D(4, 14)};
printArray(arr); // This compiles without complaint! I understand that the
// conversion is legal, but it seems like a warning
// about this would be a good idea.
}
注意:我知道这是不好的设计,但这只是为了说明一点。
这里的问题是,当按照我上面的方式混合使用这两种方法时,当我们遍历数组进行打印时,我们将不会以正确的数量来处理数组的元素(即,我们移动sizeof(Base)
而不是sizeof(D)
)。结果为输出:
10
0
11
1
12
(我猜想这样打电话operator<<
可能是UB)。
使用进行编译时,g++ -std=c++1y -Wall -Weffc++ -pedantic main.cpp
我不会收到任何警告或错误。
编译器可以进行很多静态分析,并且可以知道arr
函数中的指针用作具有意外结果的数组。
但是,这样做的速度很慢,并且会占用大量(更多)内存,并且程序员通常不耐烦,并且希望使用尽可能少的其他资源来尽可能快地完成其编译。因此,大多数编译器只进行相对快速简便的静态分析,而将艰苦的工作留给了专用的静态分析器。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句