Как я могу создать несколько объектов с циклом for в C ++? - PullRequest
9 голосов
/ 04 ноября 2011

Я пытаюсь создать несколько объектов, используя цикл for, так как в конечном итоге я хочу, чтобы эта программа создавала разные числа класса в зависимости от моего ввода. Я пытался написать это, используя ответ на предыдущий вопрос . Однако, когда я пытаюсь скомпилировать, я получаю сообщение об ошибке «нет подходящей функции для вызова« Genes :: Genes () »

#include <iostream>
#include <cstdlib>
#include <ctime> 

using namespace std;

float random();

class Genes{
 public:
 double cis;
 double coding;
 double effect;
 Genes(double a, double b, double c);
};

Genes::Genes(double a, double b, double c) 
{
  cis=a;
  coding=b;
  effect=c;
};

int main()
{
  int geneno, i;

  srand(time(NULL));

  geneno=4; //this will probably be cin later

  Genes *genes=new Genes[10]

  for(i=0;i<=geneno;i++){
    double d,e,f;

    d=random();
    e=random();
    f=random();

    genes[i]=Genes(d,e,f);

    cout<<"cis is "<<genes.cis<<'\n';
    cout<<"coding is "<<genes.coding<<'\n';
    cout<<"Effect for gene is "<<genes.effect<<'\n';

    }
 delete[] genes;
 }


float random(){

  float decRANDMAX;

 decRANDMAX=RAND_MAX*1.0;

 return rand()%(RAND_MAX+1)/decRANDMAX;

}  

Ответы [ 6 ]

10 голосов
/ 04 ноября 2011

Используйте idiomatic C ++ и выберите правильный контейнер для задания (а именно vector):

#include <vector>

const std::size_t num_genes; // your data here

//...

std::vector<Genes> v;
v.reserve(num_genes);

for (std::size_t i = 0; i != num_genes; ++i)
{
  v.push_back(Genes(random(), random(), random()));  // old-style
  v.emplace_back(random(), random(), random());      // modern (C++11)
}

Теперь у вас есть элементы в v[0], v[1] и т. Д.

8 голосов
/ 04 ноября 2011

В C ++ создание массива с помощью new [] инициализирует все объекты их конструктором по умолчанию / без параметров.

Итак, эта строка: (точка с запятой добавлена)

 Genes *genes=new Genes[10];

приведет к десяти вызовам Genes :: Genes ().

Обычно это выглядит нормально, поскольку C ++ предоставит вам конструктор по умолчанию, когда вы его не объявляете. Однако, чтобы это произошло, вы не должны объявлять никаких конструкторов. Ваш конструктор:

Genes::Genes(double a, double b, double c)

Запрещает компилятору создавать для вас конструктор по умолчанию, что, в свою очередь, не позволяет создавать массив объектов Genes.


Существует два разумных решения этой проблемы:

  1. Вы можете добавить конструктор по умолчанию / без аргументов в класс Genes. Это просто, но не хватает элегантности. Что такое объект Genes по умолчанию? Если бы такой объект имел смысл, вы, вероятно, уже объявили бы конструктор по умолчанию.

  2. Рассмотрим использование std :: vector вместо массива: http://www.cplusplus.com/reference/stl/vector/. Хотя это более сложное исправление в краткосрочной перспективе, знание Стандартной библиотеки шаблонов (которая предоставляет векторный класс) будет полезно в долгосрочной перспективе. Тем не менее, если вы только изучаете C ++ и не видели шаблонов раньше, это может быть немного ошеломляющим, и вы можете сначала немного прочитать о шаблонах. (например, на http://www.learncpp.com/cpp-tutorial/143-template-classes/)

Класс vector позволяет вам объявлять емкость для того, сколько объектов вы поместите в ваш массив (или вы не можете объявлять емкость, что приводит к более медленной вставке). Тогда он будет создавать объекты только тогда, когда они помещены в вектор. Ваш код будет выглядеть примерно так:

#include <vector> // to get the vector class definition
using std::vector; // to 

vector<Genes> genes;
genes.reserve(geneno); // optional, but speeds things up a bit

for(i = 0; i <= geneno; i++) {
    double d = random();
    double e = random();
    double f = random();

    genes.push_back(Genes(d, e, f));
}

Последнее утверждение (приблизительно) эквивалентно:

Genes temp(d, e, f);
genes.push_back(temp);

vector :: push_back добавляет элемент в конец вектора и увеличивает емкость вектора на 1: http://www.cplusplus.com/reference/stl/vector/push_back/

Впоследствии вы можете обращаться к элементам в векторе так же, как и к массиву:

cout << "The third gene's coding is " << genes[3].coding << endl;

И вы можете запросить размер вектора с помощью vector :: size ():

cout << "The vector has " << genes.size() << "elements" << endl;
3 голосов
/ 04 ноября 2011

Genes *genes=new Genes[10] создает массив из 10 пустых 'Genes', но у вас нет конструктора по умолчанию для Genes - нет способа создать 'Genes' без предоставления a, b, c.

Вам нужен пустой ctor или укажите аргумент по умолчанию для a, b, c

Genes::Genes() : cis(0),coding(0),effect(0)

or 

Genes::Genes(double a=0, double b=0, double c=0) 
1 голос
/ 04 ноября 2011

Как только вы напишите параметризованный конструктор,

Genes::Genes(double a, double b, double c);

компилятор не сгенерирует конструктор по умолчанию без параметров для вашего класса, вы должны предоставить его самостоятельно.

У вас есть два варианта:

.Вам нужно явно определить конструктор по умолчанию для вашего класса:

Genes::Genes():cis(0),coding(0),effect(0)
{
}

или

.Вы используете параметризованный конструктор (с аргументами по умолчанию) вместо конструктора по умолчанию.

Genes::Genes(double a=0, double b=0, double c=0) 
{
}
0 голосов
/ 04 ноября 2011

Существует несколько решений, которые проще всего реализовать с учетом того, что у вас есть (т.е. без изменения класса Genes и без использования класса контейнера):

geneno = 4;
Genes** genes = new Genes*[geneno] ;

Затем в цикле:

genes[i] = new Genes(d,e,f);

Преимущество этого состоит в том, что вы избегаете переполнения буфера, если geneno> 10.

Ваш код доступа (cout) в любом случае недопустим.Учитывая предлагаемое изменение, доступ к объекту будет выглядеть следующим образом:

cout<<"cis is "<<genes[i]->cis<<'\n';
cout<<"coding is "<<genes[i]->.coding<<'\n';
cout<<"Effect for gene is "<<genes[i]->.effect<<'\n';

Код очистки теперь должен будет также удалить каждый объект в массиве genes перед удалением самого массива.Одна из причин, по которой контейнерный класс может быть более подходящим.

0 голосов
/ 04 ноября 2011

Это потому, что вы сначала создаете массив Genes, используя конструктор по умолчанию в Genes* genes = new Genes[10]. Вам нужно вместо этого использовать стандартный контейнер для хранения генов, например std::vector или std::list.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...