I agree with that, except that "for compilation dependency purposes"
confuses the issue without adding any information IMHO.
How is it unclear? I've been answering C4251 questions for a long time, and
I can't recall anyone asking for clarification, but that is the most
concise way I've found to put it. I typically go into quite a bit more
detail, along the lines of what I said in this thread in my first reply to
you and in my second reply to the OP. I don't know any better way to
capture the issue in one sentence.
However, that adds a lot of limitations, and avoiding those limitations was
the whole point of the text the OP quoted and asked about.
As I explained elsewhere in this thread, the documentation was concerned
with template static data. That's the _sole_ "limitation" it talked about.
As for the COM simulation suggestion, that's just one approach (the
documentation actually links to a KB article that explains how to dllexport
template specializations to avoid the problem), and as it prevents one from
using the class as a C++ class, which is why dllexport was being used in
the first place, it throws the baby out with the bath water. The OP would
seem to agree, as he replied to you:
<q>
All this seems unnecessarily complicated - it sounds like reinventing
the (COM) wheel. Maybe I should just use the PImpl Idiom (typesafe
opaque ptr) to move all of the private data from the header file into
the implementation - that will certainly make the compiler shut up about
C4251 warnings ?
</q>
In my reply, I explained why using the pimpl idiom is often overkill just
to silence C4251, when all you may need is #pragma warning(disable),
subject, of course, to what I say in my one sentence summary you find so
confusing.
Again, in my
opinion the language you used suggested that dllexport was just as good or
better than the method suggested by the MSDN article, and this just isn't
true in many (possibly most) situations.
Given that dllexport lets you use the class as a full-fledged C++ class
instead of a poor COM simulation, the former is infinitely better than the
latter if you want to use the class as a C++ class. That's effectively what
I said in my first reply to the OP, whose last paragraph was:
<q>
Of course, the weakness of following the documentation you quoted to the
letter is that derived classes can't call X::f1(), because that's a
statically bound call and does require linking by name. You can work around
that by adding X_EXPORT to the front of your virtual functions. But then
you're just about at the point where you might as well have exported the
whole class, which is what I recommend doing if you want the thing to act
like a C++ class instead of a COM-style interface. As long as you link
everyone to the same CRT DLL and consider this usage equivalent to static
linking WRT compilation dependencies, for the most part, it'll work fine,
and you can get rid of the Create/Destroy functions, as well as all the
individual function exports, and it'll "just work".
</q>
I deliberately differentiated the approaches. I deliberately mentioned
advantages and drawbacks of both, and I expanded at length in a subsequent
message on the one major issue (template static data) concerning what
you're trying to pass off as my "pet approach" or something. It's not my
pet approach. It just bugs me when someone who clearly _has_ a pet
approach, i.e. he thinks DLLs are only to be COM-style black boxes, and any
other usage is evil, tries to pass off groundless opinions (still waiting
on those examples) as if they were facts, when the facts are, lots
(probably many thousands) of programs use dllexported classes without any
problems. (See programs that use the C, C++, and MFC DLLs.)
The real question is "what value does dllexport have over static linking"
and aside from staggered loading, I can't think of anything. I'm pretty
sure it has no value whatsoever to most projects.
It has the same value as static libraries, with the DLL advantages of
deterministic order of initialization of globals (DllMain restrictions
apply, of course), run-time code sharing (smaller code, more efficient
memory usage), and yes, the ability in some cases to fix bugs and make
other enhancements merely by replacing a DLL. It also allows one to be a
little more lax in controlling visibility of classes used internally by the
DLL, as one needn't worry about violating ODR rules between modules for
classes that aren't exposed in any way to DLL clients.