1

I wrote a simple interface: (ICopyOnOperator.h)

template<typename T>
class ICopyOnOperator {

    public:
        virtual const T& operator=(const T& other) = 0;

        ICopyOnOperator() = default;

        ICopyOnOperator(const ICopyOnOperator& other) {
            this->operator=((const T&)other);
        }
};

It is supposed to automate calling the operator= function when the copy constructor gets called. In another class I derive from it: (Vao.h)

class Vao : public ICopyOnOperator<Vao> {
   ...

   public:
        virtual const Vao& operator=(const Vao& other) override {
            return *this;
        }
};

And when I compile my code, I get the 'unresolved external symbol' error. Do you have any idea why (I know what the error message means, but why does it happen?) or how to achieve my goal differently?

[EDIT]

To make it clear. The linker cannot find the ICopyOnOperator<class Vao>::operator=(class rhino::Vao const &) method. Full error message:

1>tester.obj : error LNK2019: unresolved external symbol "public: virtual class rhino::Vao const & __thiscall rhino::ICopyOnOperator::operator=(class rhino::Vao const &)" (??4?$ICopyOnOperator@VVao@rhino@@@rhino@@UAEABVVao@1@ABV21@@Z) referenced in function "public: __thiscall rhino::ICopyOnOperator::ICopyOnOperator(class rhino::ICopyOnOperator const &)" (??0?$ICopyOnOperator@VVao@rhino@@@rhino@@QAE@ABV01@@Z)

Moritz Seppelt
  • 51
  • 1
  • 10
  • 1
    Are you linking with the object file/library exporting the function? – Jesper Juhl Apr 26 '18 at 17:51
  • I think I link the object files – Moritz Seppelt Apr 26 '18 at 17:56
  • This should compile fine with just headers only. However this code is rather pointless. First of all, virtual methods in template class lead to code bloat and in this particular case are useless because polymorphism will only be applied to the single class. Then cast `(const T&)other` will lead to undefined behavior when `other` is not an instance of `T`. CRTP can be used here, but I don't why would someone want to call operator= function when the copy constructor gets called. – user7860670 Apr 26 '18 at 18:02
  • Ok I agree. The cast is not really safe. Are there other opportunities to achieve what I want? – Moritz Seppelt Apr 26 '18 at 18:04

1 Answers1

0

This has to do with the fact that you call a virtual method (operator=) from within a constructor. Calling a virtual method from a constructor results in calling the method defined at that level of hierarchy, not the method defined in the class being instantiated.

See the accepted answer here: Calling virtual functions inside constructors

Ishamael
  • 12,583
  • 4
  • 34
  • 52
  • It does, since in the constructor it calls to `ICopyOnOperator::operator=(Vao const&)`, not `Vao::operator=(Vao const&)`, and `ICopyOnOperator::operator=(Vao const&)` is not defined anywhere. – Ishamael Apr 26 '18 at 18:11
  • It is actually defined as `virtual const T& operator=(const T& other) = 0;` in class `ICopyOnOperator`. [The given code should compile just fine](https://wandbox.org/permlink/QtgKTkIwxpVZApne). Linking error is probably caused by invalid project configuration or something. – user7860670 Apr 26 '18 at 18:15
  • Actually, `g++` doesn't compile the code you linked :) – Ishamael Apr 26 '18 at 18:17