Skip to content

Commit 87758ae

Browse files
Merge pull request #5124 from TylerMSFT/warning
improve C4251
2 parents 8793aa4 + 686c0ec commit 87758ae

File tree

1 file changed

+46
-13
lines changed

1 file changed

+46
-13
lines changed
Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,73 @@
11
---
22
description: "Learn more about: Compiler Warning (level 1) C4251"
33
title: "Compiler Warning (level 1) C4251"
4-
ms.date: 02/22/2022
4+
ms.date: 12/01/2023
55
f1_keywords: ["C4251"]
66
helpviewer_keywords: ["C4251"]
7-
ms.assetid: a9992038-f0c2-4fc4-a9be-4509442cbc1e
87
---
98
# Compiler Warning (level 1) C4251
109

1110
> '*type*' : class '*type1*' needs to have dll-interface to be used by clients of class '*type2*'
1211
1312
## Remarks
1413

14+
This warning happens if a class is marked with `__declspec(dllexport)` or `__declspec(dllimport)` and a nonstatic data member that is a member of the class or a member of one of its base classes, has a type that is a class type that isn't marked with `__declspec(dllexport)` or `__declspec(dllimport)`. See [Example](#example).
15+
1516
To minimize the possibility of data corruption when exporting a class declared as [`__declspec(dllexport)`](../../cpp/dllexport-dllimport.md), ensure that:
1617

1718
- All your static data is accessed through functions that are exported from the DLL.
18-
1919
- No inlined methods of your class can modify static data.
20-
2120
- No inlined methods of your class use CRT functions or other library functions that use static data. For more information, see [Potential errors passing CRT objects across DLL boundaries](../../c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries.md).
22-
2321
- No methods of your class (whether inlined or not) can use types where the instantiation in the EXE and DLL have static data differences.
2422

25-
You can avoid issues when exporting a class from a DLL: Define your class to have virtual functions, a virtual destructor, and functions to instantiate and delete objects of the type. You can then just call virtual functions on the type.
23+
You can avoid issues when exporting a class from a DLL by:
2624

27-
C4251 can be ignored if your class is derived from a type in the C++ Standard Library, you're compiling a debug release (**`/MTd`**), and where the compiler error message refers to `_Container_base`.
25+
- Defining your class to have virtual functions.
26+
- Defining a virtual destructor.
27+
- Defining functions to instantiate and delete instances of the type.
2828

29-
## Example
29+
You can ignore C4251 if your class is derived from a type in the C++ Standard Library, you're compiling a debug release (**`/MTd`**), and the compiler error message refers to `_Container_base`.
30+
31+
Think carefully about adding `__declspec(dllexport)` or `__declspec(dllimport)` to a class because it's almost always not the right choice and it can make maintenance more difficult because it makes changing implementation details harder.
3032

31-
This sample exports a specialized class `VecWrapper` derived from `std::vector`.
33+
## Example
3234

3335
```cpp
3436
// C4251.cpp
35-
// compile with: /EHsc /MTd /W2 /c
37+
// Compile with /std:c++20 /EHsc /W2 /c C4251.cpp
38+
#include <vector>
39+
40+
class __declspec(dllexport) X
41+
{
42+
public:
43+
X();
44+
~X();
45+
46+
void do_something();
47+
48+
private:
49+
void do_something_else();
50+
std::vector<int> data; // warning c4251
51+
};
52+
```
53+
54+
To fix this warning, don't mark the class with `__declspec(dllexport)` or `__declspec(dllimport)`. Instead, only mark the methods that are used directly by a client. For example:
55+
56+
```cpp
57+
// C4251_fixed.cpp
58+
// Compile with /std:c++20 /EHsc /W2 /c C4251-fixed.cpp
3659
#include <vector>
37-
using namespace std;
38-
class Node;
39-
class __declspec(dllexport) VecWrapper : vector<Node *> {}; // C4251
60+
61+
class X
62+
{
63+
public:
64+
__declspec(dllexport) X();
65+
__declspec(dllexport) ~X();
66+
67+
__declspec(dllexport) void do_something();
68+
69+
private:
70+
void do_something_else();
71+
std::vector<int> data;
72+
};
4073
```

0 commit comments

Comments
 (0)