Условный оператор:
pointer = (p1 != nullptr) ? p1 : p2;
Чтобы возвратить ноль, если оба не равны нулю:
pointer = (p1 && p2) ? nullptr : ((p1 != nullptr) ? p1 : p2);
Если оба равны нулю, возвращение любого из них вернет ноль.
Необходимо указать параметры конструктору в конструкторе Приложения, например.
App(int bx, int by, bsize, int rx, int ry, int rsize) :
blueSquare(bx, by, bsize), redSquare(rx, ry, rsize) {}
Это - просто пример, Вы будете, вероятно, использовать лучший дизайн IRL.
Мне кажется, что проблема возникает из присутствия "установки ()" метод. IIUC, намерение состоит в том, чтобы использовать Приложение как:
App a;
a.setup();
В каком состояние является "a" перед вызовом установка ()? То, что должно произойти, если тянут () называют на нем? Если ответ, что-то как "установка () нужно назвать перед чем-либо, что maningful мог быть сделан с объектом Приложения", затем это означает, что установка () является "настоящим" конструктором Приложения, и что текущий ctor Приложения бессмыслен. Заключение: Удалите "установку ()" метод и замените его значимым ctor.
Во-первых, необходимо выбрать, как Вы хотите, чтобы Ваш класс Приложения вел себя, если тянут (), назван перед установкой ():
Если Вы хотите иметь некоторые предопределенные квадраты по умолчанию, то инициализируйте их в списке Инициализации приложения.
Если Вы не хотите, чтобы это когда-либо произошло, то используйте указатели и защитите от этого.
Некоторые примечания по 2:
Квадратный класс имеет конструктора, который берет 3 аргумента. Класс Приложения не определяет конструктора - который подразумевает, что компилятор предоставит конструктора по умолчанию (конструктор, который не берет параметра). В конструкторе по умолчанию класса все членские переменные инициализируются конструктором по умолчанию. Так как Ваш Квадратный класс не имеет конструктора по умолчанию, Ваш код не скомпилирует.
Конструктор должен инициализировать экземпляр класса со значениями по умолчанию к его членским переменным. Если необходимо заменить какую-либо из этих переменных, то можно определить некоторый метод считывания и методы set:
class Square {
private:
int x;
int y;
int size;
public:
/* constructor */
Square(int x, int y, int size);
int getX() const {return x;}
int getY() const {return y;}
int getSize() const {return size;}
void setX(int nx) {x = nx;}
void setY(int ny) {y = ny;}
void setSize(int s) {size = s;}
}
Затем вызовите эти функции для замены внутренних переменных Квадрата.
Дайте приложению конструктора:
App :: App()
: redSquare( 10, 20, 100 ), blueSquare( 50, 500, 25 ) {
}
Я использовал бы Квадрат * вместо Квадрата как члены парламента, не занимающие официального поста Приложения. Тем путем память сохранена, конструкция Квадратных объектов в Приложении может быть отложена к при необходимости, или они могут быть сделаны в конструкторах Приложения, значения по умолчанию или иначе. Конечно, деструктор должен уничтожить два Квадратных объекта, если бы они были созданы.
Необходимо использовать указатели вместо фактических объектов.
Используя указатели заставит Ваш класс вести себя так же к Java (он вынудит Вас явно инстанцировать его на методе "установки" или конструкторе). В Java каждый объект является ссылкой (подобный {но не равный} к указателю) и нет никакого эквивалента тому, при помощи чего Вы выполняете с C++:
class A {
B b;
}
Надежда это помогает.
Почему Вы используете функцию setup/init? Используйте конструктора вместо этого, инициализирующие объекты являются смыслом существования конструктора. Объектами, которые могут существовать в неприменимых состояниях, является PItA, они требуют, чтобы каждая функция протестировала, можем ли мы делать что-либо хорошее с ними. Усильте их инвариант и запретите их существование, пока Вы не сможете полностью создать их.
Даже в Java, init/setup функции появляются мне как сомнительная практика.
Или используйте указатели или заставьте конструктора Приложения взять параметры, как предложено выше.
(in App.h)
Square* redSquare;
Square* blueSquare;
void setup(int,int,int,int);
...
(in App.cpp)
void App::setup(int x1,int y1,int x2,int y2){
redSquare=new Square(x1,y1);
blueSquare=new Square(x2,y2); // don't forget to "delete" these later
...
}
Я позволю разговору о коде. Протест: непротестированный код!
/**
Typically we will use Shape as a base class.
This defines the interface that clients of the
Shape class can expect and use reliably. Of
course, some shapes can be dough-nuts and have
a eat() method, but that's just them dough-nuts.
*/
class Shape
{
public:
/**
The base class's default ctor.
The compiler generates one if you don't specify any ctors,
but if you specify at least one, this is skipped, so we
to mention it explicitly
*/
Shape(void) {}
Shape(const std::string& c) { std::cout << c.length() << std::endl; } /* print the color */
~Shape(void) {}
/**
The interface. The '=0' makes it virtual. This class
has now become abstract. Subclasses MUST define this
member function.
*/
virtual size_t area() = 0 { return 0; }
};
/**
The more interesting objects, real world shapes.
They have their own version of implementing an
algorithm to find out area.
*/
class Circle : public Shape
{
public:
Circle(const std::string& color) /* no default parameters */
/* the base class's default ctor is called automagically */
:_color(color) /* the user must specify the color */
{}
~Circle(void) {}
virtual size_t area() /* = 0 */ /*we dont want this to be abstract! */
{ return 42; }
private:
std::string _color;
};
class Triangle: public Shape
{
public:
Triangle(const std::string& color = "red")
Shape(color)/* this base class ctor has to be called by you */
: _color(color) /* use initializer lists to populate ctor parameters */
{}
~Triangle(void) {}
virtual size_t area() { return 42 + sizeof Triangle; }
private:
std::string _color;
};
/**
We will also use design patterns. And an oft-abused
one -- the Singleton. We want only one app to run after
all.
*/
class App {
public:
/**
This would typically be in a differnt '.cpp' file.
*/
int Run() {
/* create a few shapes */
Triangle t1;
Circle c1; // error -- no default parameter
Circle c2("green");
/* You want to sum the areas of all these objects */
size_t total_area = t1.area() + c2.area();
/* Now, how do you process different shapes in one go? */
/* Put them in a container for base class pointers */
std::list<Shape *> shape_list;
shape_list.insert(&t1);
shape_list.insert(&c2);
/* process them -- calculate total area differently */
size_t total_area2 = 0;
std::list<Shape *>::iterator f = shape_list.end();
for (std::list<Shape *>::iterator i = shape_list.begin();
i != f;
++i) {
total_area2 += i->area();
/* see why we need virtual functions? */
}
/* or use the STL to the hilt and do */
size_t total_area3 = std::accumulate(shape_list.begin(), shape_list.end(),
0,
std::bind2nd(std::plus<size_t>(std::mem_fun(&Shape::area))));
}
private:
App();
App(const App&);
App& operator(const App&);
};
/* the program entry-point, you have to have one, and only one */
int main() {
App.Run();
}
Нет НИКАКОГО выхода C++ способа сделать это.
C++ путь:
Сделайте то, что Вы хотите, я дам Вам столько веревки, сколько Вы хотите.
Человек ада! Вы могли даже подвесить себя с ним, я не собираюсь останавливать Вас!
Вы могли использовать указатели, но необходимо будет знать об утечках памяти! Необходимо определить, кто (как, в который класс/объект) владеет этим объектом, у кого есть исключительное право удалить его!
ИЛИ, Вы могли плагин сборщик "мусора" (я услышал, что существуют некоторые популярные, но никогда не пробовали никого сам), и затем работайте с указателями, как будто Вы были в Java.
Если Ваша установка () действительно не имеет никаких параметров и не возвращает значений, затем помещает ту функциональность в конструктора (я предполагаю, что Вы просто пропустили тех, которые для краткости).
При наличии установки () функция, которая должна быть вызвана после конструктора, не является лучшей, но может быть совершенно допустимой, когда выдача исключения в конструкторе не является опцией. Ваша установка () функция могла решить проблемы более гибким способом.
ОДНАКО: не позволяйте конструктору оставить объект в состоянии, которое вызовет проблемы позже, конкретно:
Помещать его иначе: членская инициализация переменной похожа на наведение порядка в Вашем доме, прежде чем Ваши визиты Тещи - или сразу сделают это или поместят защиту на месте, чтобы позволить Вам, делают это, прежде чем это будет требоваться.
О, и не тратьте впустую указатели старающегося избегать большого количества времени в C++, но действительно удостоверьтесь, что Вы изучаете, как избежать ловушек.