anql
anql

Reputation: 39

C++ template <Base class and Derived class>

I'm an C++ beginner, please help me. I can't use template class as the constructor' s parameter. xcode shows 'No matching constructor for initialization of 'Work'' error. The whole source code below, any one can fix this?

#include <iostream>
class Base {
 public:
    virtual void hello_world() const {
        printf("Base::hello_world()\n");
    };
};

class Derived : public Base {
public:
    void hello_world() const {
        printf("Derived::hello_world()\n");
    };
};

template<class T>
class Templ {
public:
    Templ(const T &t) : _value(t) {}

    const T& getValue() const{
        return _value;
    }
private:
    const T &_value;
};

class Work {
public:
    Work(const Templ<Base*> &base) : mBase(base) {}

    void working() {
        mBase.getValue()->hello_world();
    }
private:
    const Templ<Base*> &mBase;
};

int main(int argc, const char * argv[]) {
    Templ<Base*> base(new Base());
    //OK
    Work w_base(base);

    Templ<Derived*> derived(new Derived());
    //error: No matching constructor for initialization of 'Work'
    Work w_derived(derived);

    return 0;
}

Upvotes: 1

Views: 263

Answers (2)

Walter
Walter

Reputation: 45434

In C++, this would look like this

struct Base
{
  virtual ~Base() {}   // enable descruction of base through pointer to Base
  virtual void hello_world() const 
  { std::cout<<"Base::hello_world()\n"; }
};

struct Derived : Base
{
  void hello_world() const override
  { std::cout<<"Derived::hello_world()\n"; }
};

struct work
{
  work(const Base*p)
  : ptr(p) {}
  void working() const
  { ptr->hello_world(); }
private:
  std::unique_ptr<const Base> ptr;
};

int main()
{
  Work w_base(new Base);
  Work w_derived(new Derived);
  w_base.working();
  w_derived.working();
}

Note the following

  1. the virtual destructor of Base ensures that a derived class is properly destructed from a pointer to Base, so that std::unique_ptr<> works correctly.
  2. the override keyword ensures that we actually implement a virtual method.
  3. the usage of std::unique_ptr<> avoids the Templ class. Morever, its destructor will automatically and correctly destroy the pointed-to object, avoiding the memory leak of your code.
  4. return 0 is not required for int main(), but automatically generated.

Upvotes: 0

NathanOliver
NathanOliver

Reputation: 180630

Work w_derived(derived); is never going to work as Work expects a Templ<Base*>. A Templ<Base*> and a Templ<Derived*> are two different, distinct types. Just a like a std::vector<int> is not the same as a std::vector<std::complex>.

What you can do though is create a Templ<Base*> from a pointer to a Dervied and then create a Work with that. Something like

Templ<Base*> derived(new Derived());
Work w_derived(derived);

Live Example

Also as pointed out in the comments since you are using polymorphism you need to have a virtual destructor in the base class. If the destructor is not virtual then only the base class destructor will run and you will your object will not be properly destructed.

Upvotes: 1

Related Questions