"collect2: error: ld returned 1 exit status" в Qt 4.8.5 при вызове коллбека

Рейтинг: 0Ответов: 2Опубликовано: 07.04.2015

есть функции и по указателю в пространствах имен "metrics.h":

namespace Metrics {
    namespace Points {
        double (*D)(mpoint* a, mpoint *b);
        extern double  Euclidean(mpoint* a, mpoint *b);
        double Mahalanobis(mpoint* a, mpoint *b);
    }
    namespace Clusters {
        double  (*D)(Cluster* a, Cluster *b);
        double  Euclidean(  Cluster* a, Cluster *b);
        double  Mahalanobis(Cluster* a, Cluster *b);
    }
}

реализация одний из них "metrics.cpp":

#include "metrics.h"
namespace Metrics {
namespace Points {
extern double Euclidean(mpoint *a, mpoint *b) {
    return (sqrt( pow((double)(a->x - b->x), 2) +  pow((double)(a->y - b->y), 2) ) );

}
...
}
...
}

Присваивание указателя ("metric_select.cpp"):

#include "metrics.h"
extern double Metrics::Points::Euclidean(mpoint*, mpoint*);
....
Metrics::Points::D = &(Metrics::Points::Euclidean);

Выдает вышеуказанную ошибку, если убрать extern'ы то выдает ее и ошибку undefined reference to Metrics::Points::Euclidean в поледней строчке Что не так? И как исправить? P.S.:Ответы со словом С++11 не принимается.

UPD: Написал структуру:

typedef struct __D{
    double (*d)(mpoint*, mpoint* );
    double operator () (mpoint*a, mpoint*b) {
        return d(a, b);
    }
    __D& operator = (double(*f)(mpoint*, mpoint*)) {
        d = f;
        return *this;
    }
} Distance;

и заменил:

double (*D)(mpoint* a, mpoint *b);

на Distanse D;

в обоих namespace'ах, ошибка та же

Ответы

▲ 1Принят

Используйте typedef.

typedef double (*Dfunc)(mpoint*, mpoint *) ;
extern Dfunc D;

Уберите extern отсюда:

extern double Euclidean(mpoint *a, mpoint *b)

В metric_select.cpp

Metrics::Points::Dfunc Metrics::Points::D = &(Metrics::Points::Euclidean);
▲ 1

Если вы пишете extern рядом с именем переменной, это означает, что переменная будет задана в другом модуле, т.н. compilation unit. Т.е. если вы пишете:

 extern Distanсe D; 

значит где-то в другом модуле у вас должно быть:

Metrics::Points::Distanсe Metrics::Points::D = 0; // инициализируем как-нибудь переменную, иначе получим unresolved external
int main()
{
    Metrics::Points::D = &(Metrics::Points::Euclidean); // теперь D содержит указатель на Euclidean
    Metrics::Points::D = &(Metrics::Points::Mahalanobis); // теперь D содержит указатель на Mahalanobis
    cout << "Hello World!" << endl;
    return 0;
}

Писать extern рядом с именем функции не имеет смысла.