2013-03-26 9 views
0

讓我們想象一下,我有一個名爲「Myclass」的類,爲它重載比較運算符是有意義的。我需要將這個類放入一個名爲「libmyclass」的庫中,我想編譯/鏈接一個名爲「myprog」的程序。在哪裏定義/聲明比較運算符的重載作爲庫中的非成員函數?

跟着advice,我選擇將比較運算符重載爲非成員函數。我選擇在頭文件中聲明它們,並在實現文件中定義它們,但是在鏈接步驟中找不到它們:「未定義的對'運算符<(...)'」的引用(見下文)。我應該怎麼做才能解決這個問題?

這裏是文件 「myclass.h」:

#ifndef MYCLASS_H 
#define MYCLASS_H 

#include <cstdlib> 

#include <string> 
using namespace std; 

class Myclass { 
private: 
    size_t x_; 
public: 
    Myclass(void); 
    Myclass(const size_t & x); 
    const size_t & GetValue(void) const { return x_; }; 
}; 

bool operator==(const Myclass& lhs, const Myclass& rhs); 
bool operator!=(const Myclass& lhs, const Myclass& rhs); 
bool operator< (const Myclass& lhs, const Myclass& rhs); 
bool operator> (const Myclass& lhs, const Myclass& rhs); 
bool operator<=(const Myclass& lhs, const Myclass& rhs); 
bool operator>=(const Myclass& lhs, const Myclass& rhs); 

#endif //MYCLASS_H 

這裏是文件 「myclass.cc」:

#include "myclass.h" 

Myclass::Myclass(void) 
{ 
} 

Myclass::Myclass(const size_t & x) 
{ 
    x_ = x; 
} 

inline bool operator==(const Myclass& lhs, const Myclass& rhs) 
{ 
    return(lhs.GetValue() == rhs.GetValue()); 
} 

inline bool operator< (const Myclass& lhs, const Myclass& rhs) 
{ 
    return(lhs.GetValue() < rhs.GetValue()); 
} 

inline bool operator!=(const Myclass& lhs, const Myclass& rhs){return !operator==(lhs,rhs);}; 
inline bool operator> (const Myclass& lhs, const Myclass& rhs){return operator< (rhs,lhs);}; 
inline bool operator<=(const Myclass& lhs, const Myclass& rhs){return !operator> (lhs,rhs);}; 
inline bool operator>=(const Myclass& lhs, const Myclass& rhs){return !operator< (lhs,rhs);}; 

這裏是文件 「myprog.c中」:

#include <cstdlib> 

#include <iostream> 
using namespace std; 

#include "myclass.h" 

int main (int argc, char ** argv) 
{ 
    Myclass * pt_obj1 = new Myclass(1); 
    Myclass * pt_obj2 = new Myclass(2); 
    if (*pt_obj1 < *pt_obj2) 
    cout << "obj1 < obj2" << endl; 
    else 
    cout << "obj1 >= obj2" << endl; 
    delete pt_obj1; 
    delete pt_obj2; 
    return EXIT_SUCCESS; 
} 

這裏是文件 「Makefile_lib」:

PROJECT=libmyclass.a 
SOURCES=myclass.cc 
CC=g++ 
CFLAGS=-Wall -Wextra -g 

OBJECTS=$(SOURCES:.cc=.o) 

all: $(PROJECT) 

$(PROJECT): $(OBJECTS) 
      ar -cvq $(PROJECT) $(OBJECTS) 

.cc.o: 
     $(CC) $(CFLAGS) -c $< -o [email protected] 

clean: 
     rm -f $(OBJECTS) $(PROJECT) 

這裏是文件「Makefile_exe」:

PROJECT=myprog 
SOURCES=myprog.cc 
LIB=libmyclass.a 
CC=g++ 
CFLAGS=-Wall -Wextra -g 

OBJECTS=$(SOURCES:.cc=.o) 

all: $(PROJECT) 

$(PROJECT): $(OBJECTS) $(LIB) 
      $(CC) $(OBJECTS) -L. -lmyclass 

.cc.o: 
     $(CC) $(CFLAGS) -c $< -o [email protected] 

clean: 
     rm -f $(OBJECTS) $(PROJECT) 

最後,這裏是我用錯我的命令:

$ make -f Makefile_lib clean 
rm -f myclass.o libmyclass.a 
$ make -f Makefile_lib 
g++ -Wall -Wextra -g -c myclass.cc -o myclass.o 
ar -cvq libmyclass.a myclass.o 
a - myclass.o 
$ make -f Makefile_exe clean 
rm -f myprog.o myprog 
$ make -f Makefile_exe 
g++ -Wall -Wextra -g -c myprog.cc -o myprog.o 
myprog.cc:8: warning: unused parameter ‘argc’ 
myprog.cc:8: warning: unused parameter ‘argv’ 
g++ myprog.o -L. -lmyclass 
myprog.o: In function `main': 
/home/me/src/myprog.cc:12: undefined reference to `operator<(Myclass const&, Myclass const&)' 
collect2: ld returned 1 exit status 
make: *** [myprog] Error 1 
+5

不要在標頭中使用* using directive *(即從標頭中刪除'using namespace std;')。 –

+0

爲什麼在內聯內聯時不能使用inline函數?! –

回答

1

你的代碼自相矛盾。

myprog.c被編譯時,operator<(Myclass const&, Myclass const&)不能被內聯。這個定義無處可見。

myclass.cc被編譯,operator<(Myclass const&, Myclass const&)因爲你承諾,這將是內聯未對連接器產生。

解決方法是刪除這些函數的inline,或者將定義移動到標題,以便它們可以真正被內聯。

1

您應該所有inline定義移到頭文件下面的聲明

0

內聯將被放在.h文件中

或刪除在.cpp內嵌文件

,可能

inline bool operator!=(const Myclass& lhs, const Myclass& rhs){return !(lhs==rhs);} 

比操作形式簡單。

並且不需要放一個;在函數定義之後。