Jakie są plusy i minusy używania niejawnych interfejsów (przypadki 2 i 3, szablony) w porównaniu do używania jawnych interfejsów (Przypadek 1, wskaźnik do klasy abstrakcyjnej) w poniższym przykładzie?niejawne vs jawne interfejsy
Kod, który nie zmienia:
class CoolClass
{
public:
virtual void doSomethingCool() = 0;
virtual void worthless() = 0;
};
class CoolA : public CoolClass
{
public:
virtual void doSomethingCool()
{ /* Do cool stuff that an A would do */ }
virtual void worthless()
{ /* Worthless, but must be implemented */ }
};
class CoolB : public CoolClass
{
public:
virtual void doSomethingCool()
{ /* Do cool stuff that a B would do */ }
virtual void worthless()
{ /* Worthless, but must be implemented */ }
};
Przypadek 1: non-matrycy klasy, która pobiera wskaźnik bazowy klasy, który zapewnia wyraźny interfejs:
class CoolClassUser
{
public:
void useCoolClass(CoolClass * coolClass)
{ coolClass.doSomethingCool(); }
};
int main()
{
CoolClass * c1 = new CoolA;
CoolClass * c2 = new CoolB;
CoolClassUser user;
user.useCoolClass(c1);
user.useCoolClass(c2);
return 0;
}
Przypadek 2: szablonowa klasa, której typ szablonu zapewnia domyślny interfejs:
template <typename T>
class CoolClassUser
{
public:
void useCoolClass(T * coolClass)
{ coolClass->doSomethingCool(); }
};
int main()
{
CoolClass * c1 = new CoolA;
CoolClass * c2 = new CoolB;
CoolClassUser<CoolClass> user;
user.useCoolClass(c1);
user.useCoolClass(c2);
return 0;
}
Przypadek 3: klasa szablonowa, której szablon jedli typ zapewnia niejawny interfejs (tym razem nie powstałymi z CoolClass:
class RandomClass
{
public:
void doSomethingCool()
{ /* Do cool stuff that a RandomClass would do */ }
// I don't have to implement worthless()! Na na na na na!
};
template <typename T>
class CoolClassUser
{
public:
void useCoolClass(T * coolClass)
{ coolClass->doSomethingCool(); }
};
int main()
{
RandomClass * c1 = new RandomClass;
RandomClass * c2 = new RandomClass;
CoolClassUser<RandomClass> user;
user.useCoolClass(c1);
user.useCoolClass(c2);
return 0;
}
Case 1 wymaga, że obiekt jest przekazany do useCoolClass() być dzieckiem CoolClass (i wdrożenia bezwartościowe ()). Natomiast przypadki 2 i 3 zajmą dowolną klasę, która ma funkcję doSomethingCool().
Jeśli użytkownicy kodu były zawsze drobnym podklasy CoolClass, następnie Przypadek 1 ma intuicyjny sens, ponieważ CoolClassUser będzie zawsze oczekiwał wdrożenie CoolClass. Załóżmy jednak, że ten kod będzie częścią struktury interfejsu API, więc nie mogę przewidzieć, czy użytkownicy będą chcieli podklasę CoolClass lub przetasować własną klasę, która ma funkcję doSomethingCool().
Niektóre pokrewne posty:
https://stackoverflow.com/a/7264550/635125
https://stackoverflow.com/a/7264689/635125
https://stackoverflow.com/a/8009872/635125
Twoje Case 1 i Case 2 nie będą się kompilować. Inicjalizacja wskaźnika przebiega w niewłaściwy sposób. – Novelocrat
@ Naprawiono wadliwą rodzinę. –