LINUX.ORG.RU

Наследование

 


0

1

Лето, температура за бортом +10, что уже радует.

Решили порешать задачки, ни у одну подкидываю.

Есть код:

#include <iostream>

class Foo {
public:
    Foo() : a_(0) {};
    Foo(int a) : a_(a) {};
    inline int getA() { return a_; };
    virtual void print() { std::cout << "{a: " << getA() << "}\n"; };
private:
    int a_;
};

class Bar : public Foo {
public:
    Bar() : Foo(), b_(0) {};
    Bar(int a, int b) : Foo(a), b_(b) {};
    inline int getB() { return b_; };
    virtual void print() override { std::cout << "{a: " << getA() << ", b: " << getB() << "}\n"; };
private:
    int b_;
};

int main() {
    Foo t1 = Bar(10,10);
    Bar t2 = Bar(20,20);
    Foo *t3 = new Bar(30,30);
    t1.print();
    t2.print();
    t3->print();
    delete t3;
    return 0;
}

Выхлоп ожидаемый:

...$ g++ -std=c++11 task.cpp && ./a.out
{a: 10}
{a: 20, b: 20}
{a: 30, b: 30}

И тут вопрос: «А как сделать вывод в первой строке такой же как в других? А чем это будет плохо?»

★★★★★

А как сделать вывод в первой строке такой же как в других?

Что разрешается изменять в программе, а что должно остаться неизменным?

А чем это будет плохо?

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

crowbar
()

А никак. Объект Bar(10,10) — временный (безымянный), он после строки с присваиванием уничтожается. А присваивается (копируется) только Foo, т. е. неявно вызывается метод Foo& Foo::operator= (const Foo&), в который в качестве параметра передаётся ссылка на временный объект.

Примерно так:

Foo t1;
t1.operator= (Bar (10, 10));

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от crowbar

Что разрешается изменять в программе, а что должно остаться неизменным?

Менять можно всё. Кроме main.

AlexVR ★★★★★
() автор топика
Ответ на: комментарий от intelfx

т. е. неявно вызывается метод Foo& operator= (const Foo&)

Только конструктор копирования. Foo foo = bar, это то же что Foo foo(bar)

crowbar
()
Ответ на: комментарий от crowbar

Ах да, copy elision. Ну сути дела это не меняет. // будем считать, что компилятор очень тупой.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от AlexVR

Точнее, только если слить два класса в один и сделать typedef из одного на другой.

intelfx ★★★★★
()

Накостылил

#include <iostream>

class Bar;
class Foo {
public:
    Foo() : a_(0) {};
    Foo(int a) : a_(a) {};
    Foo(const Bar& bar_);

    inline int getA() { return a_; };
    virtual void print();
private:
    int a_;
    Foo* foo;
};

class Bar : public Foo {
public:
    Bar() : Foo(), b_(0) {};
    Bar(int a, int b) : Foo(a), b_(b) {};
    inline int getB() { return b_; };
    virtual void print() override { std::cout << "{a: " << getA() << ", b: " << getB() << "}\n"; };
private:
    int b_;
};

Foo::Foo(const Bar& bar_) {
    foo = new Bar(bar_);
}

void Foo::print() {
    if (foo == 0)
        std::cout << "{a: " << getA() << "}\n";
    else
        foo->print();
};

int main() {
    Foo t1 = Bar(10,10);
    Bar t2 = Bar(20,20);
    Foo *t3 = new Bar(30,30);
    t1.print();
    t2.print();
    t3->print();
    delete t3;
    return 0;
}

http://ideone.com/EFP41W

crowbar
()
Ответ на: комментарий от AlexVR

Я просто под ответ подгонял, конечно надо везде это поле foo учитывать.

crowbar
()
Ответ на: комментарий от AlexVR

Халява

Менять можно всё. Кроме main.

#include <iostream>
#include <sstream>
#include <string>

class Foo {
public:
    Foo() { format_string(); }
    Foo(int a) { format_string(a); }

    void print() { std::cout << str; }
    
protected:
	std::string str;
	
	void format_string(int a = 0)
	{
		std::stringstream stream;
		stream << "{a: " << a << "}\n";
		str = stream.str();
	}
};

class Bar : public Foo {
public:
    Bar() { format_string(); }
    Bar(int a, int b) { format_string(a, b); }
    
protected:
	void format_string(int a = 0, int b = 0)
	{
		std::stringstream stream;
		stream << "{a: " << a << ", b: " << b << "}\n";
		str = stream.str();
	}
};

int main() {
    Foo t1 = Bar(10,10);
    Bar t2 = Bar(20,20);
    Foo *t3 = new Bar(30,30);
    Foo t4 = Bar(10, 20);
    t1.print();
    t2.print();
    t3->print();
    t4.print();
    delete t3;
    return 0;
}

http://ideone.com/qnfVig

Вывод:

{a: 10, b: 10}
{a: 20, b: 20}
{a: 30, b: 30}
{a: 10, b: 20}

Чем это плохо - сам догадайся

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.