2011-10-03 112 views
1

請幫忙解決關於C++和g ++編譯和鏈接的noob問題。基本上,我有2個不同的文件中的2個類,並且可以編譯它們,但是當我嘗試鏈接時,一個類無法看到另一個類的方法,即使我正在鏈接它們。目標文件的順序在這種情況下不起作用。g ++ undefined參考非常簡單的例子

該問題似乎與採用參數的非默認構造函數有關。

我已經蒸餾,轉載於下面簡單的代碼的問題:

文件:a.cpp

#include <iostream> 

class A 
{ 
    public: 
    int my_int; 
    A(int i) { 
     my_int = i; 
     std::cout << "A"; 
    } 
}; 

文件:a.hpp:

#ifndef __A_H_ 
#define __A_H_ 

class A 
{ 
    public: 
    A(int i); 
}; 

#endif 

文件b.cpp:

#include <iostream> 

using namespace std; 

#include <a.hpp> 

class B 
{ 
    public: 
    int my_int; 
    B(int i) { 
     my_int = i; 
     A a(i); 
     cout << "B\n"; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    B b(5); 
    cout << "hello world: "; 
    cout.flush(); 
    return 0; 
} 

命令我用它來構建:

g++ -c -I. a.cpp 
g++ -c -I. b.cpp 
g++ -o c_test a.o b.o 

或者,我已經嘗試每一種:

g++ -o c_test b.o a.o 
g++ -I. -o c_test a.cpp b.cpp 
g++ -I. -o c_test b.cpp a.cpp 

錯誤,我得到以上任何環節場景:

b.o: In function `B::B(int)': 
b.cpp:(.text._ZN1BC1Ei[B::B(int)]+0x1c): undefined reference to `A::A(int)' 
collect2: ld returned 1 exit status 

在此先感謝您的任何見解。

(對不起,如果這是一個重職 - 我想我張貼,並沒有看到它...)

回答

3

它不工作的方式。您遇到的情況在技術上是ODR違規,這大致意味着a.cppb.cpp中的A必須是相同的。事實並非如此。

此外,構造函數在a.cpp中隱含地爲inline,因此不需要發射它的代碼。

更改a.cpp

#include <iostream> 
#include "a.hpp" 

A::A(int i) { 
     my_int = i; 
     std::cout << "A"; 
} 

會修正這個錯誤。

1

a.cpp違反了一個定義規則,並且完全重新定義了A。你只是想在源文件中定義函數:

A::A(int i) { 
    my_int = i; 
    std::cout << "A"; 
} 

而且你可能要標記的功能明確,以避免int S爲各種不必要的上下文視爲A的。

0

a.cpp,你應該#include "a.hpp"然後定義構造函數簡單地爲A::A(int i) { ... }。通過使用構造函數代碼class體內編寫class A的完整定義,您隱式地將構造函數定義爲內聯函數,這就是爲什麼在對象文件中沒有定義它的原因。

0

您有兩個不同的類(一個包含myint,一個不包含),兩個類都被稱爲class A。你不能那樣做。更改a.cpp到:

#include <iostream> 
#include "a.hpp" 

A::A(int i) { 
    my_int = i; 
    std::cout << "A"; 
} 

並更改a.hpp到:

#ifndef __A_H_ 
#define __A_H_ 

class A 
{ 
public: 
int my_int; 
A(int i); 
}; 

#endif 

感謝一下吧,你有它的方式,你會編譯器做,如果有人這樣做:

#include "a.hpp" 
// ... 
    A foo(3); 
    cout << sizeof(foo) << endl; 

它怎麼知道class A有一個構造函數以外的成員?它怎麼能知道尺寸?

0

由於在程序中有兩個不同的獨立A類,您打破了One Definition Rule。您A.cpp文件的簡單常見的實現應該是這樣的:

#include "a.h" // where the definition of the type is 
A::A(int x) : myint(i) {} 

隨着「啊」包含類型的正確定義:

#ifndef A_H_ // identifiers containing double underscores (__) are reserved, don't use them 
#define A_H_ 
class A 
{ 
    int myint; // This must be present in the definition of the class! 
public: 
    A(int i); 
}; 
#endif; 

然後在B的實施,你可能意思是:

#include "a.h"  
#include <iostream> 

using namespace std; // I don't like `using`, but if you use it, do it after all includes! 
class B { 
public: 
// int my_int;  // do you really want to hide A::my_int?? 
    B(int i) : A(i) { // use the initializer list 
     cout << "B\n"; 
    } 
}; 
0

做正確的做法是:

a.hpp

#ifndef __A_H_ 
#define __A_H_ 

class A 
{ 
    public: 
    int my_int; 
    A(int i); 
}; 

#endif 

a.cpp

#include <iostream> 

#include "a.hpp" 

A::A(int i) { 
     my_int = i; 
     std::cout << "A"; 
    } 

b.cpp - 保持不變