[C++] zaprzyjaźnianie funkcji z klasą - def. w innym pliku


(Spwmarluk) #1

Witam,

Mam problem z deklaracją funkcji zaprzyjaźnionej z klasą w oddzielnym pliku. Pomimo załączenia pliku nagłówka, kompilator wyrzuca błąd, że obiekt klasy nie został zadeklarowany.

mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H


#include 

#include 

#include 


namespace Ui

{

    class MainWindow;

}


class MainWindow : public QMainWindow

{

    Q_OBJECT


public:


    MainWindow(QWidget *parent = 0);

    ~MainWindow();


    friend int komunikat(MainWindow &mw);


public slots:

    void pbStartClicked();


private:

    Ui::MainWindow *ui;

};


#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)

    : QMainWindow(parent), ui(new Ui::MainWindow)

{

    QTextCodec::setCodecForTr (QTextCodec::codecForName ("UTF-8"));

    ui->setupUi(this);

}


MainWindow::~MainWindow()

{

    delete ui;

}


//SLOTY


void MainWindow::pbStartClicked()

{

    ui->plainTextEdit->appendPlainText(tr("Start"));

}

fun.hpp

#ifndef _agfun_hpp_

#define _agfun_hpp_


#include "mainwindow.h"


int komunikat(MainWindow &mw);


#endif

fun.cpp

#include 


int komunikat(MainWindow &mw)

{

    mw.ui->plainTextEdit->appendPlainText(tr("Komunikat"));

    return 0;

}

main.cpp

#include 

#include "mainwindow.h"


int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    MainWindow w;

    w.show();

    return a.exec();

}

Błędy kompilacji:

fun.hpp:6: error: `MainWindow' was not declared in this scope

fun.hpp:6: error: `mw' was not declared in this scope

mainwindow.h:22: error: `int komunikat(MainWindow&)' redeclared as different kind of symbol

fun.hpp:6: error: previous declaration of `int komunikat'

fun.hpp:6: error: previous non-function declaration `int komunikat'

mainwindow.h:22: error: conflicts with function declaration `int komunikat(MainWindow&)'

Jak można to naprawić?


([alex]) #2

int komunikat(Ui::MainWindow &mw) w fun.hpp oraz fun.cpp

EDIT:

Tak a propos, czy nie będzie bardziej sensownym zrobić to jako metodę klasy MainWindow?


(Spwmarluk) #3

Po dopisaniu int komunikat(Ui::MainWindow &mw); w fun.hpp i fun.cpp otrzymałem dodatkowy błąd:

fun.hpp:6: error: `Ui' has not been declared

EDIT:

W tym przypadku oczywiście miałoby to większy sens, ale jest to tylko okrojony przykład na potrzeby pokazania błędu jaki wystąpił. W docelowym projekcie funkcje są dużo bardziej rozbudowane i podzielone na pliki pod względem ról jakie odgrywają. Wtedy wrzucanie wszystkiego do klasy MainWindow nie będzie już tak czytelne.


([alex]) #4

W mainwindow.h nie wywal #include

w fun.hpp dołączonym z mainwindow.h próbujesz odwołać się do Ui oraz MainWindow zanim zostaną zadeklarowane w mainwindow.h niżej.


(Spwmarluk) #5

Tak, już załapałem i poprawiłem to. Najpierw tworzę w mainwindow.h namespace, potem dołączam fun.hpp i się kompiluje. Jednak nie mam dostępu do danych private i protected z klasy, a przecież funkcja "komunikat" jest zaprzyjaźniona. Jak próbuję się w niej odwołać przez mw.ui ... to kompilator krzyczy, że zmienna jest typu private i koniec.

Rozwiązanie:

mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H


#include 

#include 


namespace Ui

{

    class MainWindow;

}


class MainWindow : public QMainWindow

{

    Q_OBJECT


public:


    MainWindow(QWidget *parent = 0);

    ~MainWindow();


    friend int komunikat(MainWindow* mw);


public slots:

    void pbStartClicked();


private:

    Ui::MainWindow *ui;

};


#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)

    : QMainWindow(parent), ui(new Ui::MainWindow)

{

    QTextCodec::setCodecForTr (QTextCodec::codecForName ("UTF-8"));

    ui->setupUi(this);

}


MainWindow::~MainWindow()

{

    delete ui;

}


//SLOTY


void MainWindow::pbStartClicked()

{

    ui->plainTextEdit->appendPlainText(tr("Start"));

    komunikat(this);

}

fun.hpp

#ifndef _agfun_hpp_

#define _agfun_hpp_


#endif

fun.cpp

#include 

#include "mainwindow.h"

#include "ui_mainwindow.h"


int komunikat(MainWindow* mw)

{

    mw->ui->plainTextEdit->appendPlainText("zzz");

    return 0;

}

main.cpp

#include 

#include "mainwindow.h"


int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    MainWindow w;

    w.show();

    return a.exec();

}

Wygląda na to, że definicja funkcji "komunikat" tworzona była zanim został przetworzony plik ui_mainwindow.h .

[alex] jak zwykle wielkie dzięki za pomoc.