2017-05-08 108 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 *”类型的(多态)指针指向它。 –