Предварительное объявление классов в C++

Я написал следующий код, который собирался запустить, чтобы помочь мне просмотреть наследование и то, как диспетчеризация/двойная диспетчеризация работает в C++, но он не скомпилируется. Я просмотрел прототипы/предварительные объявления классов и сделал это, но все еще получаю сообщение об ошибке «B — неполный тип», «SubB — неполный тип» и т. д. В чем проблема?

#include <iostream>

class B;
class SubB;

class A { 
    public:
        void talkTo(B b){
            std::cout << "A talking to instance of B" << std::endl;
        }
        void talkTo(SubB sb){
            std::cout << "A talking to instance of SubB" << std::endl;
        }
};
class SubA : A {
    public:
        void talkTo(B b){
            std::cout << "SubA talking to instance of B" << std::endl;
        }
        void talkTo(SubB sb){
            std::cout << "SubA talking to instance of SubB" << std::endl;
        }
};
class B { 
    public:
        void talkTo(A a){
            std::cout << "B talking to instance of A" << std::endl;
        }
        void talkTo(SubA sa){
            std::cout << "B talking to instance of SubA" << std::endl;
        }
};
class SubB : B {
    public:
        void talkTo(A a){
            std::cout << "SubB talking to instance of A" << std::endl;
        }
        void talkTo(SubA sa){
            std::cout << "SubB talking to instance of SubA" << std::endl;
        }
};

РЕДАКТИРОВАТЬ

Изменение параметров на ссылки сделало эту работу (помощь R Sahu), но почему это не работает сейчас?

class A { 
    public:
        void talkTo(B &b){
            //std::cout << "A talking to instance of B" << std::endl;
            b.talkTo(this);
        }
        void talkTo(SubB &sb){
            //std::cout << "A talking to instance of SubB" << std::endl;
            sb.talkTo(this);
        }
};
class B { 
    public:
        void talkTo(A &a){
            std::cout << "B talking to instance of A" << std::endl;
        }
        void talkTo(SubA &sa){
            std::cout << "B talking to instance of SubA" << std::endl;
        }
};
class SubB : B {
    public:
        void talkTo(A &a){
            std::cout << "SubB talking to instance of A" << std::endl;
        }
        void talkTo(SubA &sa){
            std::cout << "SubB talking to instance of SubA" << std::endl;
        }
};

A a;
SubA subA;
B b;
SubB subB;

a.talkTo(b);
a.talkTo(subB);

person Riptyde4    schedule 04.12.2015    source источник
comment
Вы, вероятно, все равно захотите использовать передачу по ссылке, если только вы никогда не хотите ни с кем разговаривать!   -  person M.M    schedule 04.12.2015
comment
да, конечно, в реальной реализации, но я просто сделал это, чтобы увидеть, какой тип проходит, я не передаю никаких данных   -  person Riptyde4    schedule 04.12.2015


Ответы (1)


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

Вместо

    void talkTo(B b){
        std::cout << "A talking to instance of B" << std::endl;
    }
    void talkTo(SubB sb){
        std::cout << "A talking to instance of SubB" << std::endl;
    }

использовать

    void talkTo(B const& b){
        std::cout << "A talking to instance of B" << std::endl;
    }
    void talkTo(SubB const& sb){
        std::cout << "A talking to instance of SubB" << std::endl;
    }
person R Sahu    schedule 04.12.2015
comment
Вы не можете сделать вызов функции с предварительным объявлением. Если вам нужно сделать вызов функции, вы должны переместить реализацию функции. Его необходимо реализовать вне определения класса и после определения классов. В вашем случае их нужно реализовать после определений классов B и SubB. - person R Sahu; 04.12.2015