// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the EXPORTCLASSDLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// EXPORTCLASSDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef EXPORTCLASSDLL_EXPORTS
#define EXPORTCLASSDLL_API __declspec(dllexport)
#else
#define EXPORTCLASSDLL_API __declspec(dllimport)
#endif
class CTest
{
public:
void fun();
};
// This class is exported from the ExportClassDll.dll
class EXPORTCLASSDLL_API CExportClassDll
{
public:
CExportClassDll(void);
// TODO: add your methods here.
public:
CTest m_test;
};

ExportClassDll.cpp

// ExportClassDll.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "ExportClassDll.h"
void CTest::fun()
{
}
// This is the constructor of a class that has been exported.
// see ExportClassDll.h for the class definition
CExportClassDll::CExportClassDll()
{
return;
}

Answers

But we have to update all CTest function as virtual, it's not a good class design.

More generally, it is not a good design to export a C++ class across a DLL boundary at all. This binds you to the specific version of the compiler, for both the DLL and the client code. In other words, you have to compile both the DLL and the client code
with exactly the same compiler and exactly the same compiler switches. Experienced C++ programmers know this, and design a DLL with a C-style interface only, using POD data types as parameters. Another alternative is a COM DLL which lets client code of any
language type to call the DLL (assuming that language is COM-aware).

you will never put implementation in ITest, put all your implementation code in CTest and override all those functions which you want to expose it to the outer world.

ITest is an interface to your CTest, the client app will never know the inner workings of CTest, so that you can change the inner workings of the CTest at your will, without worrying about breaking the client

basically, we do not want end user knows CTest
implementation, and we want end user use it by "CTest * m_pTest;", obviously,
"CTest m_test;" does not work. And we do not want export CTest for some reason.

But we have to update all CTest function as virtual, it's not a good class design.

But we have to update all CTest function as virtual, it's not a good class design.

More generally, it is not a good design to export a C++ class across a DLL boundary at all. This binds you to the specific version of the compiler, for both the DLL and the client code. In other words, you have to compile both the DLL and the client code
with exactly the same compiler and exactly the same compiler switches. Experienced C++ programmers know this, and design a DLL with a C-style interface only, using POD data types as parameters. Another alternative is a COM DLL which lets client code of any
language type to call the DLL (assuming that language is COM-aware).

you will never put implementation in ITest, put all your implementation code in CTest and override all those functions which you want to expose it to the outer world.

ITest is an interface to your CTest, the client app will never know the inner workings of CTest, so that you can change the inner workings of the CTest at your will, without worrying about breaking the client

you will never put implementation in ITest, put all your implementation code in CTest and override all those functions which you want to expose it to the outer world.

ITest is an interface to your CTest, the client app will never know the inner workings of CTest, so that you can change the inner workings of the CTest at your will, without worrying about breaking the client

in fact, I wrote the class named ITest, as an interface already, and the interface is not an abstract virtual class, it includes some un-virtual functions, those un-virtual functions are implemented in ITest.cpp, client will not see the implementation. And
I happened to the problem that client can not use those un-virtual functions.

in fact, I wrote the class named ITest, as an interface already, and the interface is not an abstract virtual class, it includes some un-virtual functions, those un-virtual functions are implemented in ITest.cpp, client will not see the implementation. And
I happened to the problem that client can not use those un-virtual functions.

An interface should contain only pure virtual functions. If a client needs to use a function, make it pure virtual in the interface and implement it in the derived class.

I just learnt MFS DLL. I have written a simple testing program which indicats that function members of the interface class (i.e. CTest, ITest) do not have to be (pure) virtual functions. If this is the case, how is it a bad design not to have (pure)
virtual member functions.

I just learnt MFS DLL. I have written a simple testing program which indicats that function members of the interface class (i.e. CTest, ITest) do not have to be (pure) virtual functions. If this is the case, how is it a bad design not to have (pure)
virtual member functions.

Yes, you can export non-virtual functions, but that is not an interface. The purpose of using ITest and CTest is to separate the interface form the implementation.

The big advantage of a pure interface in this context is that the virtual function table is implemented the same way by all compiler versions (and most compilers). This allows binary compatibility, and is the key idea behind COM.

Yes, this is a good pattern (a simplified version of COM). Note however that only the ITest definition and CreateTestInstance() declaration should be in ITest.h. The other code should be in a separate file (or files) used only in the DLL.

You also need a mechanism for deleting the instance in the DLL, or you will leak memory. This may be done either by adding a new Delete() method to the ITest interface, or by exporting another function, say DeleteTestInstance(ITest*).

in fact, I wrote the class named ITest, as an interface already, and the interface is not an abstract virtual class, it includes some un-virtual functions, those un-virtual functions are implemented in ITest.cpp, client will not see the implementation. And
I happened to the problem that client can not use those un-virtual functions.

An interface should contain only pure virtual functions. If a client needs to use a function, make it pure virtual in the interface and implement it in the derived class.

David Wilkinson | Visual C++ MVP

I found sometimes some functions are not pure virtual for interface, eg, initialize member variables function, all the derived classes need not implement it again