2016-05-03 10 views
-3

私はこのプロジェクトの最後であり、私は理解できないコンパイルエラーが発生しています。それは私をナットにしている、私はそれがクラス間のリンクエラーの問題かもしれないことを読んでいた。しかし、私はそれがどこにあるのか、どのように修正するのかを理解することはできません。C++でのコンパイルエラー

> CruiseShip.o: In function `CruiseShip': 
> /home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:8: multiple 
> definition of `CruiseShip::CruiseShip(std::basic_string<char, 
> std::char_traits<char>, std::allocator<char> >, 
> std::basic_string<char, std::char_traits<char>, std::allocator<char> 
> >, int)' CargoShip.o:/home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:8: 
> first defined here CruiseShip.o: In function `CruiseShip': 
> /home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:8: multiple 
> definition of `CruiseShip::CruiseShip(std::basic_string<char, 
> std::char_traits<char>, std::allocator<char> >, 
> std::basic_string<char, std::char_traits<char>, std::allocator<char> 
> >, int)' CargoShip.o:/home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:8: 
> first defined here CruiseShip.o: In function 
> `CruiseShip::setPass(int)': 
> /home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:12: multiple 
> definition of `CruiseShip::setPass(int)' 
> CargoShip.o:/home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:12: 
> first defined here CruiseShip.o: In function `CruiseShip::getPass()': 
> /home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:15: multiple 
> definition of `CruiseShip::getPass()' 
> CargoShip.o:/home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:15: 
> first defined here CruiseShip.o: In function `CruiseShip::print()': 
> /home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:20: multiple 
> definition of `CruiseShip::print()' 
> CargoShip.o:/home/013/w/wn/wna130030/Assignment5_test/CruiseShip.cpp:20: 
> first defined here main.o: In function `main': 
> /home/013/w/wn/wna130030/Assignment5_test/main.cpp:18: undefined 
> reference to `CargoShip::CargoShip(std::basic_string<char, 
> std::char_traits<char>, std::allocator<char> >, 
> std::basic_string<char, std::char_traits<char>, std::allocator<char> 
> >, int)' 
collect2: ld returned 1 exit status make: *** [app] Error 1 

CruiseShip.h

#ifndef CRUISESHIP_H_ 
#define CRUISESHIP_H_ 
#include <string> 
class CruiseShip: public Ship{ 
protected: 
    int maxPassengers; 


public: 
    CruiseShip(std::string name,std::string year, int maxPassengers); 
    void setPass(int); 
    int getPass(); 
    virtual void print(); 

}; 
#endif 

CruiseShip.cpp

#include <iostream> 
#include "Ship.h" 
#include "CruiseShip.h" 
using namespace std; 



CruiseShip::CruiseShip(std::string name,std::string year, int maxPassengers):Ship(name,year){ 
maxPassengers=0; 
} 

void CruiseShip::setPass(int maxPassengers){ 
    this->maxPassengers=maxPassengers; 
} 
int CruiseShip::getPass(){ 
    return maxPassengers; 

} 

void CruiseShip::print(){ 
    cout<<"The name of the ship is "<<getName()<<endl; 
    cout<<"The capacity of the ship is "<<maxPassengers<<endl; 

} 

Ship.h

#ifndef SHIP_H_ 
#define SHIP_H_ 
#include <string> 
class Ship{ 
protected: 
    std::string name; 
    std::string year; 

public: 
    //Default Constructor 
    Ship(std::string name, std::string year); 
    void setName(std::string name); 
    void setYear(std::string year);     
    std::string getName(); 
    std::string getYear(); 
    virtual void print(); 


}; 

#endif 

Ship.cpp

#include <iostream> 
#include "Ship.h" 
using namespace std; 

Ship::Ship(string name, string year){ 
name=""; 
year = ""; 

} 

void Ship::setName(string name){ 
this->name = name; 
} 
void Ship::setYear(string year){ 
    this->year=year; 
} 
string Ship::getName(){ 
    return name; 
} 

string Ship::getYear(){ 
    return year; 
} 

void Ship::print(){ 
    cout<<"The name of the ship is "<<name<<endl; 
    cout<<"The year the ship was built is "<<year<<endl; 
} 

CargoShip.h

#ifndef CARGOSHIP_H_ 
#define CARGOSHIP_H_ 
#include <string> 
class CargoShip: public Ship{ 

protected: 
    int cargoCapacity; 


public: 
    CargoShip(std::string name, std::string year,int cargoCapacity); 
    int getCapacity(); 
    virtual void print(); 

}; 

#endif 

CargoShip.cpp

#include <iostream> 
#include "Ship.h" 
#include "CruiseShip.h" 
#include "CargoShip.h" 

using namespace std; 


CargoShip::CargoShip(int cargoCapacity):Ship(name,year){ 
    this->cargoCapacity=cargoCapacity; 

} 

int getCapacity(){ 
    return cargoCapacity; 
} 
void print(){ 
cout<<"The Name of the ship is "<<getName()<<endl; 
cout<<"The ship's cargo capacity is "<<cargoCapacity<<endl; 
} 

main.cppに

#include <iostream> 
#include <iomanip> 
#include "Ship.h" 
#include "CruiseShip.h" 
#include "CargoShip.h" 

using namespace std; 

int main() 
{ 
int i; 
//An array of Ship pointers 
Ship *ships[3]={ 
new Ship("Lolipop", "1960"), 
new CruiseShip("Disney Magic","2010",2400), 
new CargoShip("Black Pearl","2003",50000) 
}; 
//Display output 
for(i=0;i<3;i++){ 
ships[i]->print(); 
} 

return 0; 
} 
+1

エラーテキストを生成するためにどのようなコマンドを実行していますか? – donjuedo

+1

精神的なデバッガは言う:CruiseShip.cppとCruiseShip。cppがあなたのmakeファイルに2度入っています –

+2

* "私はこのプロジェクトの最後です" *これは面白いです。あなたがコンパイルしているときに、リンクエラーの束を持っているとき、あなたは終わりの近くのどこにもありません。私はあなたが終わった1/2の方法よりも小さいと言いたい。 – abelenky

答えて

-1

まず、CargoShip.cppで、あなたの実装の数が不足しているCargoShip ::

例えば

int getCapacity(){ 
    return cargoCapacity; 
} 

はあなたCargoShipで

int CargoShip::getCapacity(){ 
    return cargoCapacity; 
} 
2

をする必要があります。 cppには、クラス名を忘れてしまったいくつかの関数があります:

int getCapacity(){ 
    return cargoCapacity; 
} 

void print() 
{ 
    cout<<"The Name of the ship is "<<getName()<<endl; 
    cout<<"The ship's cargo capacity is "<<cargoCapacity<<endl; 
} 

int CargoShip::getCapacity() // you may want to add const here too 
{ 
    return cargoCapacity; 
} 

...

する必要がありますまた、何らかの理由で CargoShip.cppでCruiseship.hとCargoShip.hの両方が含まれます。

いくつかの他の事:

あなたのコンストラクタは少しオフに思われる、

Ship::Ship(string name, string year) 
{ 
    name=""; 
    year = ""; 
} 

Ship::Ship(string name, string year) 
{ 
    this->name=name; 
    this->year = year; 
} 

、好ましくは、引数のための他の名前を使用する必要がありますメンバ変数を初期化するためにそれらを使用します回避するthis->

私はvirtuaを参照してくださいあなたのShipクラスのデストラクタを削除する必要があります。重大な問題が発生したオブジェクトを削除する場合は、これが必要です。

派生クラスのヘッダーに基本クラスを含める方が良い方法です。このようにして、ユーザーが派生クラスのヘッダーを使用する場合、前にどのヘッダーを含めるかを知る必要はありません。

#ifndef CRUISESHIP_H_ 
#define CRUISESHIP_H_ 
#include <string> 
#include "Ship.h"      <-- 
class CruiseShip: public Ship 
{ 

あなたはメンバ変数は、それをconstとして宣言する変更しない関数から値を返す:

... 
int getPass() const; 
... 

あなたは同様にそれをクリーンアップする、このような配列を宣言するとき、それは良いスタイルですあなたがそれを完了したときに

//An array of Ship pointers 
Ship *ships[3]={ 
new Ship("Lolipop", "1960"), 
new CruiseShip("Disney Magic","2010",2400), 
new CargoShip("Black Pearl","2003",50000) 
}; 

... 

for (int i = 0; i < 3; ++i) 
{ 
    delete ships[i]; 
} 

btwこれは、仮想デストラクタのために正しいデストラクタが呼び出されるときです。

+0

デストラクタを追加すると修正されました。ありがとう! – willh231

0

C++の知識が不足しているため、コードに多くの間違いがあります。私はあなたのShipファイルの間違いについて説明しようとします。

Ship.h

#ifndef SHIP_H_ 
#define SHIP_H_ 
#include <iostream> 
#include <string> 
class Ship{ 
private: // should be private because you just want your class to access them 
    std::string name; 
    std::string year; 

public: 
    /* default constructor because this is what is walled when you just create a variable like : Ship ship1;*/ 
    Ship(); 

    Ship(std::string, std::string); //constructor with parameters 
    // SETTERS 
    void setName(const std::string); 
    void setYear(const std::string); 
    //GETTERS 
    std::string getName() const; 
    std::string getYear() const; 

    virtual void print() const; // virtual class 
}; 

#endif 

Ship.cpp

#include "Ship.h" 

using namespace std; 

Ship::Ship(){ 
    name=""; 
    year=""; 
} 

Ship::Ship(string name, string year){ 
    this->name=name; 
    this->year = year; 
} 
// SETTERS 
void Ship::setName(const string name){ 
    this->name = name; 
} 
void Ship::setYear(const string year){ 
    this->year=year; 
} 

// GETTERS 
string Ship::getName()const{ 
    return name; 
} 

string Ship::getYear()const{ 
    return year; 
} 
void Ship::print()const{ 
    cout<<"The name of the ship is "<<getName()<<endl; 
    cout<<"The year the ship was built is "<<getYear()<<endl; 
} 

のconst関数は、変数を変更することはできませんプログラムに指示します。 getterはクラスパラメータを変更すべきではありません。あなたの例では明らかですが、それを強制するのは良い方法です。 Const変数は同じで、パラメータで渡す変数は変更できません。

存在するコンストラクタは4種類あります。デフォルトのものは、パラメータを持つコンストラクタと同じではありません。パラメータを持つコンストラクタは、クラスのパラメータをパラメータで上書きするためのものです。

cargohipの場合、CargoShip(std::string, std::string,int)を宣言すると、3つのパラメータ、文字列、文字列、およびintがあります。使用しているとき、それはあなたの関数を呼び出す必要があり、同じ名前と同じパラメーターの数と種類を小枝や、同じ関数を呼び出しません。

int main() 
{ 

    Ship *ship=new Ship("Lolipop", "1960"); 
    CruiseShip *cruiseShip=new CruiseShip("Disney Magic","2010",2400); 
    CargoShip *cargoShip=new CargoShip("Black Pearl","2003",50000); 
    //Display output 

    Ship *ships[3]={ship,cruiseShip,cargoShip}; // THIS is a really bad way to do it 

    for(int i=0;i<3;i++){ 
     ships[i]->print(); 
    } 

    return 0; 
} 

CargoShip::CargoShip(string name, string year,int cargoCapacity):Ship(name,year){ 
    // Ship constructor is called givind the parameters name and year 
    this->cargoCapacity=cargoCapacity; 
} 

main.cppには与えます私:

The name of the ship is Lolipop 
The year the ship was built is 1960 
The name of the ship is Disney Magic 
The capacity of the ship is 0 
The ship's cargo capacity is 50000 
+0

私のship.cpp&ship.hはうまくコンパイルされているようですが、コンパイラはCruiseShipのエラーをスローしていますか? – willh231

+0

それがないというエラーを投げないからではありません。アプリケーションの起動後、またはアプリケーションの起動時にエラーが発生します。私はproprelyを書く方法のサンプルを与えた、ちょうど私があなたに最初に与えたものを見てください – Hearner

+0

さて、私はそれを男に感謝します。 – willh231

関連する問題