2

I use a parent class which has some virtual methods. When I call the virtual method in the constructor, it gives LNK2019 and LNK1120 errors with "error LNK2019: unresolved external symbol "protected: virtual int ... referenced in function "public: __thiscall ... " and "...\Debug\8puzzleProject.exe : fatal error LNK1120: 1 unresolved externals" messages.

Is there way to solve this problem or shoudn't I call a virtual method in the constructor?

Thank you!

Here is the codes:

Class with errors:

#ifndef HEURISTICSEARCH_H
#define HEURISTICSEARCH_H

#include "BruteSearch.h"

class HeuristicSearch: public BruteSearch
{
public:

    HeuristicSearch( int initial[BOARD_LIMIT][BOARD_LIMIT] );
    bool search();

protected:

    virtual int calculateUtility() = 0;
    virtual int calculateUtility( Node* ) = 0;

    bool check4Goal();
    void checkNmove();
    int findMin(int* values );

    int utilityCost;

};

#endif

HeuristicSearch::HeuristicSearch( int initial[BOARD_LIMIT][BOARD_LIMIT] )
    :BruteSearch( initial )
{
    utilityCost = calculateUtility(); //After deleting this line, the error's gone
}

Parent class of the parent class (There is no error)

#ifndef BRUTESEARCH_H
#define BRUTESEARCH_H

#include <iostream>
#include <queue>

#include "Constants.h"
#include "Node.h"

class BruteSearch
{
public:

    BruteSearch( int initial[BOARD_LIMIT][BOARD_LIMIT] );
    virtual bool search(){ return false; }

protected:

    bool check4Goal();
    void printBoard();

    int turn;
    int goalBoard[BOARD_LIMIT][BOARD_LIMIT] ;

    Node *currentPtr;

};

#endif
ciyo
  • 725
  • 4
  • 16
  • 36
  • 1
    could you please post your code? Do you use your Parent class alone? It won't work without providing the implementation to virtual methods. – nio Nov 22 '13 at 11:33
  • 2
    possible duplicate of [Calling virtual functions inside constructors](http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors) – Kiril Kirov Nov 22 '13 at 11:33

2 Answers2

6

shoudn't I call a virtual method in the constructor?

Doing so will call the override in the class being constructed, not necessarily the final override. This is probably not what you want, and an error if the function is pure virtual in the current class, so generally you shouldn't.

In this case, the error suggests that it's pure virtual, and not implemented, in this class, so calling it is definitely an error. Luckily, it gave you a reasonably friendly linker error rather than undefined runtime behaviour. (UPDATE: the code you've posted confirms that guess - you can't call the function from the constructor).

Is there way to solve this problem

Many problems can be solved with an extra level of indirection. I would implement the heuristic in a separate delegate class, rather than a subclass:

struct Heuristic {
    virtual ~Heuristic() {}  // Don't forget this on a polymorphic base class
    virtual int calculateUtility() = 0;
    virtual int calculateUtility( Node* ) = 0;
};

class HeuristicSearch: public BruteSearch {
public:
    HeuristicSearch(Heuristic & h, int initial[BOARD_LIMIT][BOARD_LIMIT]) : 
        BruteSearch(initial), 
        heuristic(h),
        utilityCost(heuristic.calculateUtility()) // No problem calling this
    {}

private:
    Heuristic & heuristic;
    int utilityCost;
    // and so on
};

The delegate is fully constructed before we start to construct the Search class, so there are no issues accessing it from the constructor.

Alternatively, to avoid unnecessary runtime polymorphism, I might inject the delegate type as a template parameter:

template <class Heuristic>
class HeuristicSearch: public BruteSearch {
public:
    HeuristicSearch(int initial[BOARD_LIMIT][BOARD_LIMIT]) : 
        BruteSearch(initial), 
        utilityCost(heuristic.calculateUtility()) // Doesn't have to be virtual
    {}

private:
    Heuristic heuristic;
    int utilityCost;
    // and so on
};
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Yes, it is a pure virtual function and I implement it in the children classes. So, I guess, I got the answer. – ciyo Nov 22 '13 at 11:38
2

When you construct an object of a derived class, an object of the base class is constructed first. That object does not know that it will become an object of the derived class. Hence, any functions that are called from the constructor of the base class are resolved against the base class only, regardless of whether the function is virtual or not.

In your case, HeuristicSearch does not provide an implementation of calculateUtility, but the HeuristicSearch::calculateUtility() is called from the constuctor of HeuristicSearch, regardless of whether HeuristicSearch::calculateUtility() is virtual or not.

Oswald
  • 31,254
  • 3
  • 43
  • 68