Compiler warning for mixed array and polymorphism

In more efficient C ++, the interesting point is that mixed array and polymorphism is a bad idea. For instance,

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. } 

Note. I know this is a bad design, but to illustrate the point.

The problem is that when mixing these two methods, which I have above, when we iterate the array for printing, we will not advance the array element by the correct amount (i.e. we move to sizeof(Base) instead of sizeof(D) ) This leads to the conclusion:

 10 0 11 1 12 

[Real-time example.]

(And I suppose the call to operator<< , as this is probably UB).

When compiling with g++ -std=c++1y -Wall -Weffc++ -pedantic main.cpp I do not receive any warnings or errors.

  • Is there a compiler flag that I can enable that indicates a warning in this scenario?
  • If not, why not?
+5
source share
3 answers

The compiler could do a lot of static analysis and might know that the arr pointer in the function is used as an array with unexpected results.

However, this is slow and consumes a lot (more) of memory, and programmers are usually impatient and want their compilation to be done as quickly as possible, using as few other resources as possible. Therefore, most compilers do only static analyzes, which are relatively quick and easy, leaving the hard work to specialized static analyzers.

+2
source

void printArray(const Base arr[]) equivalent to void printArray(const Base* arr) .

It is permissible to pass a pointer of type D function whose parameter is of type const Base* . Therefore, the compiler will not generate any warnings.

+1
source

FYI, mixing arrays, and polymorphism can be performed if the polymorphism is presented as a detail of the implementation of the descriptor class:

 #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(); } } 

expected output:

 hello from A hello from B 
-1
source

All Articles