混合数组和多态性的编译器警告 在更有效的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. }

混合数组和多态性的编译器警告 在更有效的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. },c++,arrays,polymorphism,C++,Arrays,Polymorphism,(我猜调用操作符void printary(const Base arr[])相当于void printary(const Base*arr) 将类型为D的指针传递给参数类型为const Base*的函数是合法的。因此编译器不会给出任何警告。仅供参考,如果多态性作为句柄类的实现细节提供,则可以混合数组和多态性: #include <iostream> #include <vector> // a handle which will happily own any cla

(我猜调用
操作符
void printary(const Base arr[])
相当于
void printary(const Base*arr)


将类型为
D
的指针传递给参数类型为
const Base*
的函数是合法的。因此编译器不会给出任何警告。

仅供参考,如果多态性作为句柄类的实现细节提供,则可以混合数组和多态性:

#include <iostream>
#include <vector>

// a handle which will happily own any class which implements the concept
struct Thing
{
    struct concept
    {
        virtual void sayHello() const = 0;
        virtual ~concept() = default;
    };

    Thing(std::unique_ptr<concept> ptr) : _impl(std::move(ptr)) {}

    void sayHello() const { _impl->sayHello(); }

    std::unique_ptr<concept> _impl;
};

struct thing_a : Thing::concept
{
    void sayHello() const override { std::cout << "hello from A\n"; }
};

struct thing_b : Thing::concept
{
    void sayHello() const override { std::cout << "hello from B\n"; }
};

int main()
{
    std::vector<Thing> things;

    things.emplace_back(std::make_unique<thing_a>());
    things.emplace_back(std::make_unique<thing_b>());

    for (const auto& t : things) { t.sayHello(); }
}

编译器可以进行大量的静态分析,并且可以知道函数中的指针
arr
被用作一个数组,会产生意外的结果


然而,这样做很慢,而且需要很多(更多)内存不足,程序员通常不耐烦,也希望使用尽可能少的其他资源尽可能快地完成编译。因此,大多数编译器只进行相对快速和简单的静态分析,而将繁重的工作留给专用的静态分析器。

那么,
2)
的答案就是这样“警告”不是编译器必须实现的。您可以要求g++的实现者添加这样的警告(如果它还不存在的话),但根据任何标准,他们都不会被迫这么做。@PaulMcKenzie,没错,但GCC的警告远远不止这些,我想知道检测这一点是否有技术上的困难?你必须问问组装编译器的工程师。答案可能从“这是个好主意”到“我们没有时间”不等它已经存在了。@PaulMcKenzie我希望它是3。@Slava,是的,我知道,因此,
注:我知道这是一个糟糕的设计,但只是为了说明一点。
我只是想知道是否有编译器对此发出警告。编译器可以对合法的构造发出警告。我知道这是合法的行为,
int-arr[5];arr[6]=10,我们得到了一个警告。@Ben假设在第三个库中定义了
printary
,并且没有函数调用将
D
类型的指针传递给该库中的
printary
。编译器不会抱怨任何事情。但是,当有人使用库时,会传递
D类型的指针e> 对于
printary
。我认为编译器检查第三个库中
printary
的实现,查看
printary
是否需要
Base
类型的数组不是一个好主意。他问的是数组对基类指针的衰减,而不是对
Derived
ge的指针的警告它被传递给那些将指针指向
Base
的函数。一旦数组退化为指针,有多个元素的静态信息就消失了,但是如果您注意到,他询问的是一个场景,在这个场景中,编译器可以决定性地知道参数是派生类型的衰减数组,并且知道签名是declared表示一个类型为
Base
的数组。由于编译器在发出警告时一再证明能够进行相对复杂的静态分析,他想知道为什么这种静态分析不会发生。这是如何回答这个问题的?@Barry我想这个网站的目的是回答问题和进行教育ate。事实是,如果安全地进行多态性处理,多态性可以与向量包含兼容。这是安全地进行多态性处理的方法之一。答案与教育有关。因此,我假设你认为1)的答案是否定的。@Ben可能是否定的。如果文档中没有提到任何此类警告,那么唯一确定的方法就是获取源代码(如果有)并阅读:我真的不相信减慢编译速度的说法,因为警告通常是可以关闭的。因此,任何关心安全的人都可以打开它们,而所有关心编译速度的人都可以离开它们off@tobi303您通常仍然需要警告,即使在构建包含成千上万个文件的项目时也是如此(如由专门的过梁进行的全面静态分析可能意味着一个适度长的休息时间)。
#include <iostream>
#include <vector>

// a handle which will happily own any class which implements the concept
struct Thing
{
    struct concept
    {
        virtual void sayHello() const = 0;
        virtual ~concept() = default;
    };

    Thing(std::unique_ptr<concept> ptr) : _impl(std::move(ptr)) {}

    void sayHello() const { _impl->sayHello(); }

    std::unique_ptr<concept> _impl;
};

struct thing_a : Thing::concept
{
    void sayHello() const override { std::cout << "hello from A\n"; }
};

struct thing_b : Thing::concept
{
    void sayHello() const override { std::cout << "hello from B\n"; }
};

int main()
{
    std::vector<Thing> things;

    things.emplace_back(std::make_unique<thing_a>());
    things.emplace_back(std::make_unique<thing_b>());

    for (const auto& t : things) { t.sayHello(); }
}
hello from A
hello from B