Skip to content

Commit 746fe09

Browse files
TylerMSFTTylerMSFT
authored andcommitted
improve C4251
1 parent 8793aa4 commit 746fe09

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed
Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,69 @@
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 non-static 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 defining your class to have virtual functions, a virtual destructor, and functions to instantiate and delete objects of the type. You can then call virtual functions on the type.
2624

2725
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`.
2826

29-
## Example
27+
Think carefully about adding `__declspec(dllexport)` or `__declspec(dllimport)` to a class because it is almost always not the right choice and it can make maintenance more difficult because it makes changing implementation details harder.
3028

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

3331
```cpp
3432
// C4251.cpp
35-
// compile with: /EHsc /MTd /W2 /c
33+
// Compile with /std:c++20 /EHsc /W2 /c C4251.cpp
34+
#include <vector>
35+
36+
class __declspec(dllexport) X
37+
{
38+
public:
39+
X();
40+
~X();
41+
42+
void do_something();
43+
44+
private:
45+
void do_something_else();
46+
std::vector<int> data; // warning c4251
47+
};
48+
```
49+
50+
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:
51+
52+
```cpp
53+
// C4251_fixed.cpp
54+
// Compile with /std:c++20 /EHsc /W2 /c C4251-fixed.cpp
3655
#include <vector>
37-
using namespace std;
38-
class Node;
39-
class __declspec(dllexport) VecWrapper : vector<Node *> {}; // C4251
56+
57+
class X
58+
{
59+
public:
60+
__declspec(dllexport) X();
61+
__declspec(dllexport) ~X();
62+
63+
__declspec(dllexport) void do_something();
64+
65+
private:
66+
void do_something_else();
67+
std::vector<int> data;
68+
};
4069
```

0 commit comments

Comments
 (0)