I have a library which I'm porting to Windows/MSVC. The library is C++, and uses the following pattern to hide the implementation. I'm trying to use the suggested way to export the entire class with dllexport on the class declaration.
#define API __declspec(dllexport)
class API Something
{
public:
static Something * instantiate();
void doSomething() = 0;
// etc
};
Then there is a private implementation which implements the static factory method and all the other methods.
// SomethingImpl.h
class SomethingImpl : public Something
{
//... normal overrides
}
// SomethingImpl.cpp
Something * SomethingImpl::instantiate()
{
return new SomethingImpl();
}
void SomethingImpl::doSomething()
{
// something great
}
However when I think link the DLL to my application, all these symbols are not found by the linker (LNK2019). I suppose that because they are pure virtual methods it assumes they are not needed? Any hints?
The other more normal classes are linking OK, and when I see the DLL in dependency walker, the symbols are definitely not there for these classes.
Thanks
Your assumption is correct in the sense, that the base class (Something) is not exported. More specifically, there is no actual code generated for the base class (since it is a pure virtual class). Hence there are no symbols that could be exported.
On the derived class (SomethingImpl) however you have to dllexport the private implementation for the consumer of the dll. The dllexport of the base class is not inherited by the derived class. But you have to export these symbols in order of allowing a consumer actually using this code. That does not mean your implementation details become "public" to the consumer.
As an example, imagine a consumer of your dll declares a class with a member of type Something. When this class calls Something::instantiate(), the linker needs to know which actual address needs to be called. Hence your implementation must be exported.
Related
I'm working on a simple C++ program and am having a difficult time understanding a compiler error I was getting. The issue was caused by me attempting to create a derived class from a base class. I've posted my code below with the same structure but have changed the names.
BaseClass.h
#ifndef BASECLASS_H
#define BASECLASS_H
class BaseClass {
public:
BaseClass(void);
virtual int method1(void) = 0;
virtual int method2(void) = 0;
virtual float method3(void) = 0;
};
#endif // BASECLASS_H
DerivedClass.h
#ifndef DERIVEDCLASS_H
#define DERIVEDCLASS_H
#include "DerivedClass.h"
class DerivedClass: public BaseClass
{
public:
DerivedClass(void);
};
#endif // DERIVEDCLASS_H
DerivedClass.cpp
#include "DerivedClass.h"
DerivedClass::DerivedClass(void)
{
}
int DerivedClass::method1(void)
{
// TODO
}
int DerivedClass::method2(void)
{
// TODO
}
float DerivedClass::method3(void)
{
// TODO
}
When attempting to compile this, I get the following error for all the virtual methods:
no 'int DerivedClass::methodX()' member function declared in class 'DerivedClass'
As soon as I declare these methods in the 'DerivedClass.h', the errors go away since the compiler is now aware of the methods.
However, I'm confused. Why was it necessary to re-declare the pure virtual functions in DerivedClass.h? When I #include DerivedClass.h, that will automatically include BaseClass.h, thus I assume my DerivedClass.cpp should be fully aware of the methods. Am I doing something incorrect?
It doesn't work this way. You need to declare the methods you're going to define, whether they're overriding a virtual method or not.
This isn't just an unreasonable requirement of the language. Without this you would be unable to define partially virtual class, i.e., you could have BaseSubtype that has common implementation of method1() but requires classes derived from it to implement method2() and method3()
When you declare a method in a derived class, you say to the compiler:
I want to override this method in this class
So if you don't declare a method in the derived class, you say:
I don't want to override this method; derived class's implementation is the same as the one in the base class
In your case, the base class declares them as pure virtual, so in this case it can be paraphrased:
I don't want to implement this method in this class
If you try to define a method but not declare it, you contradict yourself. The compiler detects that (to protect you from your own negligence).
A very non-intuitive reason why overridden virtual methods must be derived in the base class stems from the fact that C++ allows different parts of the class to be placed into different files, into different translation units.
With some other languages (I'm looking in Java's direction), a single class must be placed in a single file. This is not true with C++. It is perfectly legal for a class to have some of its methods declared in one translation unit, and other methods declared in another translation unit, which could be in a file in some different directory altogether.
Each such file gets compiled separately and individually. When compiling one translation, the C++ compiler has no knowledge of any other translation unit, any other file, that might contain other pieces of the same class.
Now let's say that you are allowed to omit an overriden virtual method from the class declaration. This creates an immediate problem: when compiling the class's constructor, it is necessary for the compiler to know whether the class overrides any virtual methods from any of the superclasses, in order to correctly assemble the virtual table dispatch for the class being constructed. Without an explicit declaration, the compiler has no way of knowing whether or not some other translation unit might define an overridden virtual method.
And that's why overridden virtual methods must be explicitly included in the class's declaration. In conclusion: because C++ formally specifies phase 9, the linkage phase, with the actual compilation carried on in earlier phases, overridden methods must be explicitly declared.
you should override all the base class pure virtual functions to be able to instantiate derived class.
you cannot define a base class member function from derived class.
in your example you are trying to define method1 and method2 and method3 which are not members of DerivedClass!! you have to declare them yourself in your derived class. compiler doesn't do it for you.
so your Derivedclass.h will look like:
#ifndef DERIVEDCLASS_H
#define DERIVEDCLASS_H
#include "BaseClass.h"
class DerivedClass: public BaseClass
{
public:
DerivedClass(void);
virtual int method1(void); // not pure function
virtual int method2(void);
virtual float method3(void);
};
#endif // DERIVEDCLASS_H
I've been lots of threads on this subject but I still miss the whole picture.
Suppose I have a program structure like this and I want to build the project as a shared library:
class Parent
{
public:
virtual double foo1() =0;
virtual double foo2() =0;
double foo3();
}
class Daughter1 : public Parent
{
public:
double foo1();
double foo2();
}
class Daughter2 : public Parent
{
public:
double foo1();
double foo2();
}
class evenmorecomplex:
{
public:
evenmorecomplex(const &Parent);
//
}
in lots of threads, I saw there is a declaration of
extern "C"
{
//functions for which I want to prevent the mangling
}
So my problem is double:
1) doesn't this method trash all the C++ object design?
2) obviously I can't declare two identical functions in the same scope...so, how can I export all the methods in this case?
Thanks everyone will make me things clearer.
[EDIT] Some more questions...just to understand better (sorry but I'm still a newbie in C++)...
3) if I had a non-virtual method (say foo3() ) in Parent, should I export also the Parent class, or the inherited (non-virtual) foo3 will be automatic "captured" while exporting Daughter1 and Daughter2? Should I selectively export that method in the Parent class?
4) suppose Parent is called in the constructor of another class (as reference)...since Parent can't be initialized the point is making the constructor to accept both Daughter1 and Daughter2. The question is: if I export only Daughter1 and Daughter2 (and evenmorecomplex) will this constructor still work?
This is compiler specific.
extern "C" is only useful when you want to export functions C style, if you want to export functions C style you won't be able to export functions with C++ calling conventions (such as any class functions)
On Windows / Visual-Studio, simply prefix your class with __declspec( dllexport ) when exporting or __declspec( dllimport ) when importing, like this:
class __declspec( dllexport ) MyClass{
float somefloat = 12.0f;
void fucn();
}
http://msdn.microsoft.com/en-us/library/81h27t8c.aspx
To use the same header, for both importing and exporting the class, you probably want to create a define/macro.
EDIT:
3&4, All base classes must be exportable, you can not inherit an exportable class from an non-exportable class. Its described in more detail here: http://msdn.microsoft.com/en-us/library/81h27t8c.aspx
Functions exported from an library outside of an "extern "C"" block like this are not callable from any language besides C++.
If you want to be able to call the functions from a different language, you either have to only export C functions, or export a COM interface.
I have already seen a post about the error but This is some what different. So please donot close this. I have an Interface class and I have a class that inherits the interface class and overides the methods in Interface class. The code looks likes this
//interface file
//Interface.h
class A
{
virtual method1();
};
//b.h
#include "Interface.h"
class B : public A
{
//declaration
}
//b.cxx
#include b.h
B::method1()
{
//definition
}
I am exporting all these classes in a dll. And I am using methods and classes in the dll from an exe. This exe agains contains somes classes. These classes again inherit the same interface file and also uses method1(). So to use method1() I am including b.h in my file. If order of my include statements are Interface.h and b.h, then I am getting Compiler error for exe. Telling "base class not defined". But if I reorder the Include statement there is no compilation error. Can any one suggest me what could be basic reason for this problem.
There are actually two errors in your example code: First you do not declare the method without a return type, which is an error. The second is that you, at least in the snippet above, do not declare method1 in the class definition of B:
class B : public A
{
virtual void method1();
};
You absolutely need to declare virtual method "method1()" in both A and B's class definition.
If you interface is IA and is declared in IA.h , make sure that every class Foo that inherits from IA be it in the exe or dll includes IA.h before the class definition in Foo.h
What I suspect is happening that this is not the case and based on the header include order you might be getting the definition of IA in certain files and not in the others
After reading this article: Using Interfaces in C++
I have decided to use the __interface keyword with a macro that will add virtual destructors as described in the above link.
I was happy that the __interface keyword will cause the compiler to enforce interface rules, but I was disappointed when I took it for a test drive... It turns out that the __interface keyword does not enforce the rule that a method in the interface should not contain a method body.
I can of course add a macro for function methods but I don't want to do this. Does anyone have any other suggestions?
EDIT: portability is a none issue for me because i must compile on both windows and linux so i will use the __interface keyword when i'm on windows and not on linux , that will be in order to enforce the below rules , which can't be enforced via abstract base class:
Can inherit from zero or more base interfaces.
Can only contain public, pure virtual methods.
Cannot contain data members; properties are allowed.
Cannot inherit from a base class.
Cannot contain constructors, destructors, or operators.
Cannot contain static methods.
besides the destructor issue which can be workaround one can see the advantage of using this keyword in windows env of course.
There is no interface keyword in Standard C++ as in Java, What you have in C++ are Abstract Base Classes.
An Abstract Base Class is a class which has atleast one pure virtual function and an object of such a class cannot be created but a pointer or reference to it can be created. Thus it can be used to simulate the behavior of interfaces.
Example of Abstract class as an interface
class Shape
{
public:
virtual void draw()=0;
};
class Rectangle:public Shape
{
public:
void draw()
{
//draw a Rectangle
}
};
int main()
{
Shape *ptr = new Rectangle();
ptr->draw(); //calls draw() of Rectangle class
return 0;
}
Note that:
__interface keyword as a new Microsoft extension to the C++ compiler.
That is non C++ Standard specified and Non portable.
EDIT: This answer was to a question titled "__interface keyword Win c++" and was tagged C++.
__interface is a microsoft specific extension. It's not standard and not portable.
Also, C++ allows for pure virtual method to have function body.
class Base {
virtual void foo () = 0;
};
void Base::foo ()
{ } // ok
It's advisable to explicitly declare virtual destructor in the class body.
Greetings all,
I come from Java background and I am having difficulty with multiple inheritance.
I have an interface called IView which has init() method.I want to derive a new class called PlaneViewer implementing above interface and extend another class. (QWidget).
My implementation is as:
IViwer.h (only Header file , no CPP file) :
#ifndef IVIEWER_H_
#define IVIEWER_H_
class IViewer
{
public:
//IViewer();
///virtual
//~IViewer();
virtual void init()=0;
};
#endif /* IVIEWER_H_ */
My derived class.
PlaneViewer.h
#ifndef PLANEVIEWER_H
#define PLANEVIEWER_H
#include <QtGui/QWidget>
#include "ui_planeviewer.h"
#include "IViewer.h"
class PlaneViewer : public QWidget , public IViewer
{
Q_OBJECT
public:
PlaneViewer(QWidget *parent = 0);
~PlaneViewer();
void init(); //do I have to define here also ?
private:
Ui::PlaneViewerClass ui;
};
#endif // PLANEVIEWER_H
PlaneViewer.cpp
#include "planeviewer.h"
PlaneViewer::PlaneViewer(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
PlaneViewer::~PlaneViewer()
{
}
void PlaneViewer::init(){
}
My questions are:
Is it necessary to declare method init() in PlaneViewer interface also , because it is already defined in IView?
2.I cannot complie above code ,give error :
PlaneViewer]+0x28): undefined reference to `typeinfo for IViewer'
collect2: ld returned 1 exit status
Do I have to have implementation for IView in CPP file (because all I want is an interface,not as implementation) ?
A good way to think about interface classes is that they specify what methods derived classes MUST implement.
Is it necessary to declare method
init() in PlaneViewer interface also ,
because it is already defined in
IView?
The quick answer is that yes you must implement the init method in IViewer because in the base class the method is declared as pure virtual. This means that any derived class MUST provide its own implementation of that method as there is no base class method implemented.
2.I cannot complie above code ,give error :
PlaneViewer]+0x28): undefined
reference to `typeinfo for IViewer'
collect2: ld returned 1 exit status
This is a g++ compiler error that indicates (as stated above) that you have a derived class from a base that has a pure virtual function and that the derived class does not implement the pure virtual method, as it must.
Oh and it should also be noted that you are not having an issue with multiple inheritance, the problem would still exist if only IViewer and PlaneViewer were involved.
Yes, you have to declare init in your PlaneViewer as well. If you didn't, then init wouldn't exist in PlaneViewer and PlaneViewer would still be considered abstract (because there's no implementation of init).
You need to define empty bodies for your (virtual) destructor in IViewer. "Interfaces" in C++ are not really interfaces, it's only by convention that you create a class with all pure-virtual methods and no fields: however, they're still just "regular" classes from the compiler's point of view, so you still need to provide an implementation of the destructor.
class IViewer
{
public:
IViewer() { }
virtual ~IViewer() { }
virtual void init() = 0;
};
Is it necessary to declare method init() in PlaneViewer interface also , because it is already defined in IView?
You do not have to declare init() in PlaneViewer, but if you don't PlaneViewer will be an abstract class, meaning that you cannot instantiate it.
If you mean to ask if you have to have 'void init();' in the header file for PlaneViewer and in the .cpp file. The answer is yes.
I cannot complie above code ,give error :
PlaneViewer]+0x28): undefined reference to `typeinfo for IViewer' collect2: ld returned 1 exit status
I think either you are not building the same code or your compile command is incorrect.
I stripped out the QT stuff and was able to build your code just fine with g++.
The error means that the IViewer class was not found by the linker.
I get that error if I remove the '=0' part that makes 'IViewer::init()' a pure virtual function. You could also get that error if you uncommented the constructor and/or destructor in IViewer.
Do I have to have implementation for IView in CPP file?
No. C++ does not care if it is in a .cpp file or a .h file. Unlike Java, the C/C++ preprocessor first resolves all the includes and generates one file containing all the code. It then passes this to the C/C++ compiler. You can actually include a .cpp if you want. Not a good idea though.
The typeinfo issue is caused by not having an implementation of a destructor for the IViewer class. Typically compilers will generate internal data structures (eg. "typeinfo") along with the virtual destructor.
You need to compile and link a file that contains:
#include "iviewer.h"
IViewer::~IViewer() { }
It is good practice to have a virtual destructor because this gives the compiler a compilation unit to use RTTI information, and it also allows the delete operator to work correctly when called on a base class pointer.
Others have answer the question on the init() method, but in summary: If you are going to implement it in PlaneViewer, you need to declare it.
Yes, you need to re-declare virtual void init() in the subclass and implement it, because IViewer declares the function to be pure virtual.
See another question for the explanation of your error. It's caused by declaring a virtual function (not pure) and not defining it. It's not apparent from the code you posted, so I suspect you may have stale object files that were not rebuilt (you have commented out IViewer constructor and virtual destructor).
As an additional note, you should provide virtual destructors with empty body for your interfaces.
I've done significant work in both languages and there is a cookie cutter pattern you can usually follow to turn a Java interface into a c++ interface:
// Start with the Java Interface
interface Numeric {
public int toInteger();
public double toDouble();
};
C++ predates Java and doesn't bother defining the special "interface" keyword for pure virtual classes. So you effectively have to do some work that the Java compiler does automatically:
// The equivalent C++ class
class Numeric {
private:
Numeric(const Numeric&);
Numeric& operator=(const Numeric&);
public:
Numeric() {}
virtual ~Numeric() {}
virtual int toInteger() = 0;
virtual double toDouble() = 0;
};
Another good rule to follow in C++ is, whenever you inherit from a base class with pure virtual methods, re-declare them in the derived class even if you leave them as pure virtuals. It doesn't hurt performance and it lets everybody know that the object is only a partial implementation.