2013-08-15 11 views
6
class Base 
{ 
public: 
    void operator()() { func(); } 
private: 
    virtual void func() {} 
}; 

class Derived1 : public Base 
{ 
private: 
    void func() override {/*do something*/} 
}; 

class Derived2 : public Base 
{ 
private: 
    void func() override {/*do something else*/} 
}; 

Bo chcę używać przeciążanie operatorów,
referencyjny jest lepszym rozwiązaniem niż wskaźnik.C++ odniesienia klasa bazowa zainicjować z innej klasy pochodzi obiektu

Co mam zamiar zrobić to tak:

if (condition) { 
    Base& obj = Derived1(); 
} else { 
    Base& obj = Derived2(); 
} 

Ale obj zostać zniszczone i koniec zakresu.

Base& obj; 
if (condition) { 
    obj = Derived1(); 
} else { 
    obj = Derived2(); 
} 

nie będzie działać albo,
ponieważ potrzebują odniesienie być inicjowane na deklaracji.

Gdy próbuję:

Base& obj = condition ? 
    Derived1() : Derived2(); 

Mimo błędu Ponieważ operator trójargumentowy spodziewać typu cabrio.

Jakie jest najlepsze rozwiązanie tego problemu?

Odpowiedz

4

Nie można użyć ?: w tym przypadku jako Derived1 i Derived2 są różnych typów.

Jednym z możliwych sposobów jest użycie wskaźnika, to jest ważne:

condition ? pObj.reset(new Derived1()) : pObj.reset(new Derived2()); 

Albo

#include <memory> 
std::unique_ptr<Base> pObj; 
if (condition) 
{ 
    pObj.reset(new Derived1()); 
} 
else 
{ 
    pObj.reset(new Derived2()); 
} 

Można zadzwonić operator() w ten sposób:

(*pObj)(); 
+0

Korzystanie wskaźnik oznacza, muszę używać obj-> operator(), i tracą naturalną składnię przeciążenia operatora. – gnephiak

+0

zobacz moją zaktualizowaną odpowiedź, nie musisz zadzwonić -> i nie traci ona przeciążenia operatora – billz

+0

Mimo że używa wskaźnika, wciąż jest najlepszą odpowiedzią na moje potrzeby. – gnephiak

0

to będzie działać:

Base* obj; 
if (condition) { 
    obj = new Derived1; 
} else { 
    obj = new Derived2; 
} 

a potem na końcu kodu trzeba dodać

delete obj 
1

Można modyfikować swój kod jak poniżej

Base *obj1; 
if (condition) { 
    obj1 = new Derived1(); 
} else { 
    obj1 = new Derived2(); 
} 
Base &obj = *obj1; 

Ale upewnij się usunąć obj1 później

1

If chcesz referencję, nie możesz związać z nią tymczasowego, chyba że jest to const Base &. Oznacza to, że trzeba rzeczywistego obiektu do wiązania, więc zacznijmy, że:

Derived1 d1; 
Derived2 d2; 

Można jednak uzyskać non-const odwołanie z funkcji (w tym lambda). Jeśli lambdy nie są dostępne, normalna funkcja musiałaby przyjmować d1 i d2 jako parametry.

auto choose = [&](bool b) -> Base & { 
    if (b) {return d1;} 
    else {return d2;} 
}; 

Teraz tworzenie obj jest łatwe:

Base &obj = choose(condition); 
+0

To jest faktycznie działające rozwiązanie, ale z nadmiarowym obiektem. Przyjmuję odpowiedź Billza jako właściwą. – gnephiak

+0

@gnephiak, Niestety, nie sądzę, aby można było obejść to bez jakiejś wskazówki. Myślę, że możesz technicznie użyć inteligentnego wskaźnika i mieć 'Base & obj = * ptr.get();', a następnie upewnij się, że nie używasz 'obj' po tym, jak' ptr' wychodzi poza zakres. – chris

+0

Jeśli zbędny obiekt jest w porządku (jest na stosie mimo wszystko), możesz po prostu użyć static_cast zamiast hacky lambda: 'Base & obj = condition? static_cast (d1): static_cast (d2); ' – iano

Powiązane problemy