Mam więc abstrakcyjną klasę bazową bez abstrakcyjnych metod. W celu egzekwowania abstrakcyjność, mam ogłoszony (nietrywialne) destruktora jako czysto wirtualne:Czyste wirtualne dziedziczenie, wielokrotne dziedziczenie i C4505
class AbstractClass
{
public:
AbstractClass()
{
std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
}
virtual ~AbstractClass() = 0
{
std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
}
};
class ConcreteClass : public AbstractClass
{
public:
ConcreteClass()
{
std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
}
virtual ~ConcreteClass()
{
std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
}
};
To buduje i działa zgodnie z oczekiwaniami; wyjście do bloku kodu, który po prostu wyznacza wystąpienie ConcreteClass jest
AbstractClass::AbstractClass() ConcreteClass::ConcreteClass() ConcreteClass::~ConcreteClass() AbstractClass::~AbstractClass()
Teraz, kiedy ma pochodzić AbstractClass z innej klasy stosowanych jako klasy interfejsu sam mający (trywialne) destructor wirtualna (czystą lub w inny sposób) , to nadal działa:
class IAlpha
{
public:
virtual ~IAlpha() = 0 {}
};
class AbstractClass : public IAlpha
{
public:
AbstractClass()
{
std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
}
virtual ~AbstractClass() = 0
{
std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
}
};
class ConcreteClass : public AbstractClass
{
public:
ConcreteClass()
{
std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
}
virtual ~ConcreteClass()
{
std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
}
};
problem pojawia się, gdy próbuję wdrożyć dwa różne interfejsy w ten sposób:
class IAlpha
{
public:
virtual ~IAlpha() = 0 {}
};
class IBeta
{
public:
virtual ~IBeta() = 0 {}
};
class AbstractClass : public IAlpha, public IBeta
{
public:
AbstractClass()
{
std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
}
virtual ~AbstractClass() = 0
{
std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
}
};
class ConcreteClass : public AbstractClass
{
public:
ConcreteClass()
{
std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
}
virtual ~ConcreteClass()
{
std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
}
};
w tym momencie, kiedy bu ilding, otrzymuję następujące ostrzeżenie:
warning C4505: 'AbstractClass::~AbstractClass' : unreferenced local function has been removed
O dziwo jednak, wyjście nadal pokazuje AbstractClass::~AbstractClass()
nazywa uzyskiwanie.
Czy to błąd w MSVC9 (VS 2008)? Czy mogę bezpiecznie zignorować to ostrzeżenie?
Edycja: Próbowałem oddzielić definicje czystych wirtualnych metod od definicji klasy, ponieważ najwyraźniej składnia = 0 {}
jest nieprawidłowa. Niestety nadal pojawia się C4505, czy określam inline
czy nie.
Ponieważ nie znalazłem sposobu na ostrzeżenie dla tych metod (ostrzeżenie zostanie wywołane z innych części kodu), być może trzeba będzie usunąć czysty wirtualny specyfikator z AbstractClass
i polegać na tworzeniu konstruktorów chroniony. Nie jest to idealne rozwiązanie, ale przebije rearchitekcję hierarchii klas, aby obejść błędne ostrzeżenie.
Próbowałem kod w linku; dostaje to samo ostrzeżenie, mimo że, jak poprzednio, działa poprawnie po uruchomieniu. – somethingdotjunk