C++ Inheritance via dominance warning
Everything is absolutely valid. A compiler is allowed to warn about valid code, no problem here. You can try silencing the warning with a using
declaration. If this doesn't work (probably due to an MSVC bug), silence it with a pragma
.
Visual Studio Compiler warning C4250 ('class1' : inherits 'class2::member' via dominance)
I had the same warning for the following code:
class Interface
{
public:
virtual void A() = 0;
};
class Implementation : public virtual Interface
{
public:
virtual void A() {};
};
class ExtendedInterface : public virtual Interface
{
virtual void B() = 0;
};
class ExtendedImplementation : public ExtendedInterface , public Implementation
{
public:
virtual void B() {};
};
This bug report for Visual C++ 2005 in msdn suggests that this is a known bug that was considered not important enough to fix... They suggest to disable the warning in this case by using a pragma. I think it is safe also in your case, but you should use virtual inheritance as shown in the answer by Gal Goldman.
What causes C4250 (class inherits member via dominance) when using boost serialization with a virtual base class?
The reason is in fact the is_virtual_base_of
check from boost type traits. This check-construct will generate warning C4250 if the check is successful, as can be seen by this example:
...
struct base {
virtual void mf() { };
};
struct derived_normal : public base {
virtual void mf() { };
};
struct derived_virt : virtual public base {
virtual void mf() { };
};
int main() {
using namespace std;
cout << "boost::is_virtual_base_of<base, derived_normal>::value reports: ";
// The following line DOES NOT cause C4250
cout << boost::is_virtual_base_of<base, derived_normal>::value << endl;
cout << "boost::is_virtual_base_of<base, derived_virt> reports: ";
// The following line causes C4250:
cout << boost::is_virtual_base_of<base, derived_virt>::value << endl;
...
FWIW, the usage of this type-traits tool in boost serialization goes like this:
- macro
BOOST_EXPORT_CLASS
->- macro
BOOST_CLASS_EXPORT_IMPLEMENT
->struct guid_initializer
(in export.hpp) ->- (...) void_cast.hpp /
void_cast_register
-> is_virtual_base_of is used here
- macro
As far as I can tell the warning is completely harmless in this case and can be prevented by wrapping the header in:
#pragma warning( push )
#pragma warning( disable : 4250 ) // C4250 - 'class1' : inherits 'class2::member' via dominance
#include ...
#pragma warning( pop ) // C4250
Virtual inheritance and delegated implementation
This problem has been discussed previously. Dani van der Meer's answer specifically addresses this issue. It's been filed as a won't fix bug report in Visual Studio since 2005.
If you're not a fan of disabling warnings, you could always make the function selection explicit.
class B : public IB, public A
{
public:
+ int AnInt()
+ {
+ return A::AnInt();
+ }
int AnInt2()
{
return 4;
}
};
Diamond-inheritance scenario compiles fine in G++, but produces warnings/errors in VC++/Eclipse
What is the correct way of doing this? Does the code above produce undefined behavior?
The code is perfectly valid. There is no Undefined Behavior here.
An unqualified call of A()
through a DerivedC
class object, will always call DerivedA::A()
, while an unqualified call of B()
through a DerivedC
class object, will always call the DerivedB::B()
instance.
Visual C++ gives you a warning because your code uses a less commonly known feature of virtual Inheritance which may not be obvious to most common users and might surprise them. In this case, the warning should be taken as an Informative Nitpick rather than a warning.
Note that the C++ Standard does not restrict compilers from emitting informative warnings for perfectly valid code.
The documentation for warning C4250 gives an example which tells you why visual C++ chooses to give this warning.
Inaccessible direct base' caused by multiple inheritance
This has nothing to do with overriding functions. It has to do with conversions. It really doesn't have to do with accessibility (i.e "private" or such) directly either. Here is a simpler example
struct A { int a; };
struct B : A { };
struct C : B, A { }; // direct A can't be referred to!
You can refer to the indirect A
object by first converting to B
and then to A
:
B *b = &somec;
A *a = b;
You cannot do such with the direct A object. If you try to directly convert to A
, it will have two possibilities. It follows that it is impossible to refer to the non-static data members of the direct A
object given a Derived
object.
Notice that accessibility is orthogonal to visibility. Something can be accessible even tho it's not visible (for example by refering to it by a qualified name), and something can be visible even though it's not accessible. Even if all the above derivations would be declared private
, the problem would still show up: Access is checked last - it won't influence name lookup or conversion rules.
Also, anyone can cast to an unambiguous private base class with defined behavior (the C++ Standard makes an exception for this) using a C-style cast, even if normally access wouldn't be granted to do so. And then there are still friends and the class itself that could freely convert.
Related Topics
Bring Window to Front -> Raise(),Show(),Activatewindow() Don't Work
Mbcs Error Building Mfc C++ Project with Visual Studio
Best Way to Write a Linux Daemon
Documenting Preprocessor Defines in Doxygen
Performance of Std::Function Compared to Raw Function Pointer and Void* This
Why Can't a Forward Declaration Be Used for a Std::Vector
How to Calculate Offset of a Class Member at Compile Time
Boost Graph Copy and Removing Vertex
How to Check for Inf (And | Or) Nan in a Double Variable
Linux, Need Accurate Program Timing. Scheduler Wake Up Program
C++ Makefile on Linux with Multiple *.Cpp Files
Piping Input into a C++ Program to Debug in Visual Studio
How to Use External Dlls in Cmake Project
C++ Arrays as Function Arguments
Why Is Std::For_Each a Non-Modifying Sequence Operation
0Xc0000005: Access Violation Reading Location 0X00000000