2017-05-08 132 views
0

這是發生錯誤的方法。 這裏的目標是產生一定數量的基於模型晶粒(模型)的砂粒,對於給定的小時間增量dt。 穀物是一個抽象類,因爲它純粹是虛擬的方法,它必須是這樣的。 問題上xcode C++錯誤:分配抽象類類型'Grain'的對象

for(size_t a(0); a<vect.size(); ++a){ 
    vect[a] = new Grain(*modele); 
} 

似乎沒有這個初始化循環,矢量返回所有相同的穀物,但我需要他們會略有不同(在Aleatoire類提供了必要的工具)。 例如,如果我這樣做

for(size_t a(0); a<vect.size(); ++a){ 
    vect[a] = modele; 
} 

錯誤消失,但矢量返回包含所有相同的穀物,他們都是最後一粒從設定循環

std::vector<Grain*> Source::creation(std::vector<Grain*> grains, double dt){ 
vector<Grain*> vect; //vide par defaut 

Aleatoire generateur(1); 

//determiner nombre de grains a generer: DEBUT ALGO 
double fraction = debit*dt; // fraction = debit "vrai", mais a priori non entier 
int nombre(fraction);  // partie entière 
fraction -= nombre;  // partie fractionnaire 
// on ajoute 1 au hasard, proportionnellement à la partie fractionnaire : 
if (generateur.uniforme(0.0, 1.0) < fraction) ++nombre; 
//---FIN ALGO--- 
cout<<"Pour un pas de temps "<<dt<<" on genere "<<nombre<<" grains."<<endl; 

double x, y, z, r; 
vect.resize(nombre, nullptr); 

for(size_t a(0); a<vect.size(); ++a){ 
    vect[a] = new Grain(*modele); 
} 
cout<< "APRES LA FONCTION RESIZE, la taille du tableau est : "<<vect.size()<<endl; 

for(size_t i(0); i<nombre; ++i){ 
    (vect[i])->setPosition(position); //Le grain genere est genere a la position de la source 
    x = generateur.gaussienne(vitesse_iMoyenne.getCoord_x(), ecart_typeVitesse); 
//  cout<<"x = "<<setw(2)<<x<<" "; 
    y = generateur.gaussienne(vitesse_iMoyenne.getCoord_y(), ecart_typeVitesse); 
//  cout<<"y = "<<setw(2)<<y<<" "; 
    z = generateur.gaussienne(vitesse_iMoyenne.getCoord_z(), ecart_typeVitesse); 
//  cout<<"z = "<<setw(2)<<z<<" "; 
    Vecteur3D v(x,y,z); 
//  cout<<"Le nouveau vecteur vitesse est : "<<setw(2)<<v<<" "<<endl; 
    vect[i]->setVitesse(Vecteur3D(x,y,z)); 
//  cout<<"Le vecteur vitesse copie est : "<<setw(2)<<vect[i]->getVitesse()<<" "<<endl; 

    r = generateur.gaussienne(modele->getRayon(), ecart_typeRayon); 
//  cout<<"Le nouveau rayon est : "<<setw(2)<<r<<" "<<endl; 
    vect[i]->setRayon(abs(r)); 
//  cout<<"Le rayon copie est : "<<vect[i]->getRayon()<<" "<<endl; 

//  cout<<"Affichage dans la methode, dans la boucle for : "<<endl; 
//  cout<<setw(2)<<i<<" "<<*(vect[i])<<endl; 
//  cout<<endl; 
} 

// cout<<"Affichage dans la methode du vecteur de grains generes : "<<endl; 
// for(size_t j(0); j<vect.size(); ++j){ 
//  cout<<setw(2)<<j<<" "<<*(vect[j])<<endl; 
// } 
// cout<<endl; 
return vect; 
} 

這裏是Grain.hpp:

#ifndef Grain_hpp 
#define Grain_hpp 
#include "Vecteur3D.hpp" 
#include "Dessinable.hpp" 

class Grain : public Dessinable { 
public: 
Grain(Vecteur3D p={0.0,0.0,0.0}, Vecteur3D v={0.0,0.0,0.0}, double m =    1.0, double r = 1.0, Vecteur3D f = {0.0,0.0,0.0}, SupportADessin* support = nullptr); 

virtual ~Grain(); 

double masse() const; 

//eta_milieu est la constante de viscosite du milieu 

double lambda() const; //coef de frottement fluide 

void ajouteForce(); 

void bouger(double pas); 

virtual void affiche(std::ostream& sortie) const ; 

void setVitesse(Vecteur3D const& v); 

void setPosition(Vecteur3D const& p); 

void setRayon(double const& r); 

Vecteur3D getPosition() const; 

double getRayon() const; 

Vecteur3D getVitesse() const; 

Vecteur3D calcule_force() const; 

virtual Vecteur3D* vecteurForce(Grain* grain) const =0; 



//Methodes forces virtuelles 

virtual void ajouteForce(Obstacle* obstacle) = 0; 

virtual void ajouteForce(Grain* grain) = 0; 

virtual void ajouteForce(Vecteur3D) = 0; 

//Dessinable 


Grain(SupportADessin* vue) 
: Dessinable(vue) 
{} 

virtual void dessine() override; 

protected: 

Vecteur3D position; 

Vecteur3D vitesse; 

double m_volumique; 

double rayon; 

Vecteur3D force; 

}; 
std::ostream& operator<<(std::ostream& sortie, Grain const& g) ; 
#endif /* Grain_hpp */ 
+1

爲什麼'穀物'有純虛函數呢? – NathanOliver

+1

如果不是不言而喻的話,那麼這個錯誤就不算什麼。 '糧食'是一個抽象類。你的純粹虛擬成員鞏固了這一地位。所以...停止嘗試製作具體的實例。 – WhozCraig

+0

感謝@WhozCraig的評論。 那麼我知道我不能創建一個抽象類的具體實例,但在這裏我只是指向一個指針。 沒有任何東西禁止做可能不同但屬於同一個超類的異構對象集合。 就像後來成爲飛機汽車潛艇等的一系列車輛一樣。 –

回答

0

在你的情況,似乎你想克隆一個現有的對象。如果您知道要複製的對象的類型,則可以使用複製構造函數。假設下面的抽象基類,它的具體子類:

class AbstractBase { 
public: 
    virtual void print() = 0; 
}; 

class ConcreteClass : public AbstractBase { 
public: 
    ConcreteClass(int initVal) : testVal(initVal) {}; 
    virtual void print() { cout << "ConcreteClass with testVal " << testVal << endl; } 
    int testVal; 
}; 

int main() {  
    ConcreteClass *cObj = new ConcreteClass(5); 
    AbstractBase* copyOfCObj = new ConcreteClass(*cObj); 
    copyOfCObj->print(); // output: ConcreteClass with testVal 5 
    return 0; 
} 

注意,代碼沒有指定一個單獨的拷貝構造函數,所以編譯器將生成一個默認的拷貝構造函數(實際上克隆所有的數據成員) 。如果這還不夠,請定義您自己的拷貝構造函數;但這是一個單獨的主題。

如果您不知道要克隆的對象的具體類型(例如,因爲您只是有一個指向它的指針,並且此指針在其他地方被分配了一個對象),則需要一些自定義代碼(參見例如,Copying a Polymorphic object in C++)。據我所知,C++不提供內置的「克隆」功能,除非你知道這個對象的具體類型;所以你必須提供你自己的「克隆」功能,它帶來這種類型的信息:

class AbstractBase { 
public: 
    virtual AbstractBase* clone() = 0; 
    virtual void print() = 0; 
}; 

class ConcreteClass : public AbstractBase { 
public: 
    ConcreteClass(int initVal) : testVal(initVal) {}; 

    virtual ConcreteClass* clone() { 
     return new ConcreteClass(*this); 
    } 

    virtual void print() { cout << "ConcreteClass with testVal " << testVal << endl; } 

    int testVal; 
}; 

int main() { 
    AbstractBase* modele = new ConcreteClass(10); 
    AbstractBase* copyOfModele = modele->clone(); 
    copyOfModele->print(); // output: ConcreteClass with testVal 10 
    return 0; 
} 
+0

感謝您的回答,不幸的是,我希望做的事情,如果可能的話,是一個clone()方法,也適用於抽象對象。方法creation()根據抽象對象的模型創建一個指向抽象對象的指針向量,因此抽象對象的副本或克隆...我不知道我想要做的是可能,如果不是,我可能會考慮針對某個具體的子對象制定這種方法。 但是接下來的事情是,創造必須能夠根據穀物的不同子目標來創造穀物的載體...... –

+0

無論是通過複製,克隆還是無法實現抽象類的實例以某種方式嘗試創造它。您可以創建具體對象,儘管類型爲「AbstractClass *」的指針可能指向它們。請注意,對象本身仍然是一個具體的對象,即使「AbstractClass *」類型的(多態)指針指向它。 –