Почему эта программа на C ++ выдает ошибку во время компиляции, хотя передается прямое объявление? - PullRequest
2 голосов
/ 01 ноября 2011

Код:

#include<iostream>

using namespace std;

class MyClassOne;

class MyClassTwo
{
    int myInteger;
    float myFloat;

public:
    void SetData(int myIntegerParameter, float myFloatParameter)
    {
        myInteger = myIntegerParameter;
        myFloat = myFloatParameter;
    }
    void Show(MyClassOne myObjectParameter)
    {
        cout<<"MyClassOne..."<<"\n";
        cout<<myObjectParameter.myInteger<<"\n";
        cout<<myObjectParameter.myFloat<<"\n";

        cout<<"MyClassTwo..."<<"\n";
        cout<<myInteger<<"\n";
        cout<<myFloat<<"\n";
    }
};

class MyClassOne
{
    int myInteger;
    float myFloat;

public:
    void SetData(int myIntegerParameter, float myFloatParameter)
    {
        myInteger = myIntegerParameter;
        myFloat = myFloatParameter;
    }
    friend void MyClassTwo :: Show(MyClassOne);
};

int main()
{
    MyClassOne myObjectOne;
    myObjectOne.SetData(10, 10.5);

    MyClassTwo myObjectTwo;
    myObjectTwo.SetData(20, 20.5);

    myObjectTwo.Show(myObjectOne);

    return 0;
}

Сообщение об ошибке:

1>friend_function.cpp(22) : error C2027: use of undefined type 'MyClassOne'
1>friend_function.cpp(6) : see declaration of 'MyClassOne'
1>friend_function.cpp(22) : error C2228: left of '.myInteger' must have 

class/struct/union
1>friend_function.cpp(23) : error C2027: use of undefined type 'MyClassOne'
1>friend_function.cpp(6) : see declaration of 'MyClassOne'
1>friend_function.cpp(23) : error C2228: left of '.myFloat' must have 

class/struct/union
1>Generating Code...
1>Build log was saved at "file://Debug\BuildLog.htm"
1>Problem_05___Friend_Function - 4 error(s), 0 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

Ответы [ 3 ]

3 голосов
/ 01 ноября 2011

MyClassTwo::Show ожидает полного определения MyClassOne.

Переместите тело метода Show на после определения MyClassOne, и оно будет работать.

1 голос
/ 01 ноября 2011

Поскольку вы не можете использовать предварительное объявление, кроме как для предоставления указателей на объекты.

Вместо этого вы можете сделать следующее:

//MyClassTwo.h
//declaration in header
void Show(MyClassOne* myObjectParameter);

и переместить реализацию в файл cpp:

//MyClassTwo.cpp
void MyClassTwo::Show(MyClassOne* myObjectParameter);
{
    cout<<"MyClassOne..."<<"\n";
    cout<<myObjectParameter->myInteger<<"\n";
    cout<<myObjectParameter->myFloat<<"\n";

    cout<<"MyClassTwo..."<<"\n";
    cout<<myInteger<<"\n";
    cout<<myFloat<<"\n";
}

Форвардное объявление позволяет вам использовать указатель, так как все они имеют одинаковый размер.Использование фактического экземпляра будет означать, что вам нужно знать размер объекта, поскольку он будет помещен в стек аргументов метода.Но вы не знаете размер, так как его объявление еще не встречалось.Изменение порядка объявления приведет к ошибке при объявлении друга.

Разделение реализации и объявления - путь.

0 голосов
/ 01 ноября 2011

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

В частности, вам нужно иметь определение MyClassOne выше определения MyClassTwo, если вы ожидаете, что MyClassTwo получит доступ к членам MyClassOne.

Кроме того, это будетхорошая идея передать MyClassOne как ссылку на const функции-члену MyClassTwo::Show().Поэтому вы должны переопределить его как:

void Show(const MyClassOne &myObjectParameter) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...