ссылка на абстрактный класс - PullRequest
9 голосов
/ 16 февраля 2011

Что это значит, когда есть ссылка на абстрактный класс?Я нашел это в коде и не могу понять это.

Я думал, что абстрактный класс не может быть создан.Как вы можете дать ему ссылку?

Ответы [ 4 ]

13 голосов
/ 16 февраля 2011

Ссылка на абстрактный класс похожа на указатель на абстрактный класс: она должна ссылаться на объект некоторого неабстрактного подкласса абстрактного класса. Подобную ссылку можно использовать для вызова виртуальных методов в указанном классе с использованием синтаксиса ., аналогично указателю на интерфейс в Java.

8 голосов
/ 16 февраля 2011

Абстрактный класс предназначен для наследования от. Принцип подстановки Лискова примерно гласит, что все, что использует абстрактные части типов, производные от абстрактной базы, должно работать одинаково хорошо при использовании базы полиморфно. Это означает, что следует использовать ссылку или указатель на базу.

6 голосов
/ 16 февраля 2011
class Abstract
{
public:
  virtual void foo() = 0;
};

class Implementation : public Abstract
{
public:
  void foo() { std::cout << "Foo!" << std::endl; }
};

void call_foo(Abstract& obj) { obj.foo(); } 

int main()
{
  Abstract *bar = new Implementation();

  call_foo(*bar);

  delete bar;
}

bar - это pointer для абстрактного класса. Его можно разыменовать с помощью оператора * и передать как reference в call_foo, потому что это то, что call_foo запрашивает (Abstract* будет запрашивать указатель, тогда как Abstract& запрашивает ссылка).

В приведенном выше примере ссылка на абстрактный класс передается, и когда foo() вызывается с использованием нотации . (вместо нотации указателя ->), она печатает Foo!, потому что это то, что Implementation делает.

Надеюсь, это поможет.

2 голосов
/ 20 февраля 2012

Ссылки в c ++ ведут себя (почти) как скрытые указатели.В частности, то же самое полиморфное поведение, которое вы можете получить с помощью указателя, вы можете достичь с помощью ссылки.То есть следующие (почти) эквивалентны

int *i = &a;
int &j = a;

при условии, что a было целым числом, определенным где-то в предыдущих строках.Следующие вхождения ссылки j, полностью эквивалентны вхождениям (* i).Основное отличие состоит в том, что ссылка не дает вам проблем с управлением памятью, в то время как указатель делает это (вы несете ответственность за обработку новых и удаленных файлов).Кроме того, указатель не должен указывать на что-то, в то время как ссылка не может существовать, если она ни на что не ссылается.Кроме этого, вы можете считать, что они ведут себя одинаково.

Следовательно, абсолютно законно иметь ссылку на абстрактный объект.Это часто встречается в сигнатурах функций, где полиморфное поведение может быть достигнуто с помощью ссылок или указателей.Но ссылки дают более легкий синтаксис, как показано в следующем фрагменте кода

A a;
A* ptr = &a;
A& ref = a;
ref();
ptr->operator()();
(*ptr)();

при условии перегрузки класса A operator ().

...