Originally Posted by
Twey
So one can't include custom headers containing Q_OBJECT in a header. OK.
No, you can do this. The problem you have encountered has nothing to do with Q_OBJECT.
Suppose you have such project:
// a.h
#ifndef __A_H__
#define __A_H__
class A
{
public:
virtual int foo();
};
int A::foo() { return 10; }
#endif
// b.h
#ifndef __B_H__
#define __B_H__
#include "a.h"
class B : public A
{
public:
int foo();
};
#endif
// b.cpp
#include "b.h"
int B::foo() { return 20; }
// main.cpp
#include <iostream>
#include "a.h"
#include "b.h"
int main()
{
A a;
B b;
std::cout << a.foo() << b.foo() << std::endl;
}
// a.h
#ifndef __A_H__
#define __A_H__
class A
{
public:
virtual int foo();
};
int A::foo() { return 10; }
#endif
// b.h
#ifndef __B_H__
#define __B_H__
#include "a.h"
class B : public A
{
public:
int foo();
};
#endif
// b.cpp
#include "b.h"
int B::foo() { return 20; }
// main.cpp
#include <iostream>
#include "a.h"
#include "b.h"
int main()
{
A a;
B b;
std::cout << a.foo() << b.foo() << std::endl;
}
To copy to clipboard, switch view to plain text mode
As you see there are two .cpp files and to obtain the executable you must compile each of those files and link them toghether.
First those files will be go through preprocessor that will turn them to something like this:
// main.cpp
<code from iostream header>
class A
{
public:
virtual int foo();
};
int A::foo() { return 10; }
class B : public A
{
public:
virtual int foo();
};
int main()
{
A a;
B b;
std::cout << a.foo() << b.foo() << std::endl;
}
// b.cpp
class A
{
public:
virtual int foo();
};
int A::foo() { return 10; }
class B : public A
{
public:
virtual int foo();
};
int B::foo() { return 20; }
// main.cpp
<code from iostream header>
class A
{
public:
virtual int foo();
};
int A::foo() { return 10; }
class B : public A
{
public:
virtual int foo();
};
int main()
{
A a;
B b;
std::cout << a.foo() << b.foo() << std::endl;
}
// b.cpp
class A
{
public:
virtual int foo();
};
int A::foo() { return 10; }
class B : public A
{
public:
virtual int foo();
};
int B::foo() { return 20; }
To copy to clipboard, switch view to plain text mode
As you can see both of these files contain the implementation of the A::foo() method. So after compilation both main.o and b.o files will have the code for that method and linker will raise an error as it won't be able to determine which one is valid.
b.o(.text+0x0): In function `A::foo()':
b.cpp: multiple definition of `A::foo()'
main.o(.text+0x0):main.cpp: first defined here
collect2: ld returned 1 exit status
To solve the problem you should either make A::foo() an inline method or move it to a.cpp file.
Bookmarks