Implicit copy constructor and inheritance - c++

I know this kind of question has been asked many times, and I've read different answers about it, as well as some parts of the ISO standard.
But still, I need a few clarifications about the exact behaviour expected by the C++ standard.
Assuming this:
class A
{
public:
A( void ) {}
A( const A & a ) {}
};
class B: public A
{
public:
B( void ) {}
B( const B & b ) {}
};
I know that calling the copy constructor of the B class won't call the copy constructor of the A class, and that we can use an initialisation list in order to do it properly.
I also know about using using in order to inherit constructors.
But what does the standard exactly mandates about a derived class which does not provides explicitly a copy constructor, while the base class does:
class A
{
public:
A( void ) {}
A( const A & a ) {}
};
class B: public A
{};
I always thought the compiler would implicitly define a copy constructor for class B, thus hiding the copy constructor of class A, which won't be called.
However, looks like it's not the case, and the the A copy constructor is called.
Compiling with Clang on OS X 10.10.
So is this something mandatory, or something that can be implementation defined, meaning we should not rely on this behaviour?
In the C++ standard, I've found the following, but it's clearly not crystal-clear to me:
An inheriting constructor for a class is implicitly defined when it is
odr-used (3.2) to create an object of its class type (1.8). An
implicitly-defined inheriting constructor performs the set of
initializations of the class that would be performed by a user-written
inline constructor for that class with a mem-initializer-list whose
only mem-initializer has a mem-initializer-id that names the base
class denoted in the nested-name-specifier of the using-declaration
and an expression-list as specified below, and where the
compound-statement in its function body is empty (12.6.2).
I would really enjoy a clarification on it, in accordance with the standard, and also with multiple inheritance in mind.

From http://en.cppreference.com/w/cpp/language/copy_constructor (emphasis mine):
Implicitly-defined copy constructor
If the implicitly-declared copy constructor is neither deleted nor
trivial, it is defined (that is, a function body is generated and
compiled) by the compiler if odr-used. For union types, the
implicitly-defined copy constructor copies the object representation
(as by std::memmove). For non-union class types (class and struct),
the constructor performs full member-wise copy of the object's bases
and non-static members, in their initialization order, using direct
initialization.
So it seems that compiler generated copy constructor will call the base copy constructor just as it calls the copy constructors of the members.

Related

What is Compiler Generated constructor for abstract class no data members

I'm running a static analysis tool and getting an error because an abstract class, with no data members, has no constructors.
Given an abstract class with no data members:
class My_Interface
{
public:
virtual void interface_function(void) = 0;
};
Are any constructors generated by the compiler?
If a constructor is generated, what would it's content be?
If a constructor is generated, would it be eliminated by an
optimization level?
The rule documentation in the static analysis says:
If you do not write at least one constructor in a class, the compiler will
write a public constructor for you by default. This rule detects if you
do not declare at least one constructor.
The rule documentation references Scott Meyers, "Effective C++: 55 Specific Ways to Improve your Programs and Design", third edition.
My understanding is that the compiler will not generate constructors for the above case.
Edit 1:
This is not a duplicate of many constructor questions because:
This one has no data members.
This is not asking if a constructor is necessary, but what happens
when a constructor is not provided.
This is C++ language.
The compiler at least theoretically synthesizes a constructor even in this case. Even though you can't create an instance of this class, the constructor will be invoked in the process of creating a derived class (that overrides interface_function, so it can be instantiated).
Given that this is basically a pure interface class, the constructor probably won't do anything, so most compilers will probably optimize it out (quite possibly even when you don't tell it to optimize the code).
Are any constructors generated by the compiler?
Yes. Several. First, from [class.ctor]:
A default constructor for a class X is a constructor of class X that either has no parameters or else each
parameter that is not a function parameter pack has a default argument. If there is no user-declared constructor
for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted (8.4).
An implicitly-declared default constructor is an inline public member of its class. A defaulted default
constructor for class X is defined as deleted if:
Several bullet points follow, none of which apply. So we have the equivalent of:
My_Interface() = default;
Then, from [class.copy]:
If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted; otherwise, it is defined as defaulted (8.4).
So we have:
My_Interface(const My_Interface&) = default;
Also:
If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly
declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.
So we also have:
My_Interface(My_Interface&& ) = default;
If a constructor is generated, what would it's content be?
All three are generated, all three are = default;
If a constructor is generated, would it be eliminated by an optimization level?
None of the three constructors are trivial because My_Interface has a virtual function. As such, at the very least, the vtable will need to be initialized/copied. So something will have to happen, even if there aren't any members to initialize/copy/move.
Q1. Are any constructors generated by the compiler?
Answer: Yes. From the C++11 Standard:
12.1 Constructors
5 A default constructor for a class X is a constructor of class X that can be called without an argument. If
there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared
as defaulted (8.4). An implicitly-declared default constructor is an inline public member of its class.
I don't see anything in the standard that answers the other two questions. However, in your case, since there is a virtual member function, the default constructor must, at least, set the virtual table of the object.

c++ Inheriting private copy constructor: how doesn't this yield a compile time error?

In C++, if we have this class
class Uncopyable{
public:
Uncopyable(){}
~Uncopyable(){}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
and then we have a derived class
class Dervied: private Uncopyable{
};
My question is: why won't this generate a compile time error when the compiler generates the default copy constructor and assignment operators in the derived class ? Won't the generated code try to access base class private members ?
C++11 12.8/7 states "If the class definition does not explicitly declare a copy constructor, one is declared implicitly." so Dervied has an implicitly declared copy constructor. 12.8/11 says:
An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:
a variant member with a non-trivial corresponding constructor and X is a union-like class,
a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
for the copy constructor, a non-static data member of rvalue reference type, or
for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
Specifically, the third bullet applies: Dervied has a direct base class Uncopyable that cannot be copied because overload resolution results in a function that is inaccessible from Dervied::Dervied(const Dervied&). As a result Dervied's implicitly declared copy constructor is declared as deleted, resulting in a compile time error if and only if that copy constructor is called.
why won't this generate a compile time error when the compiler generates the default copy constructor and assignment operators in the derived class ?
Because the compiler generates them only when they are needed by the code being compiled. Write some code using the derived class where the copy constructor and/or assignment operator are involved, and you will see the compile-time error you are looking for.
The private in the inheritance makes them private to Derived, it can still see them, classes that use Derived can't.
The derived class will inherit the private copy constructor but will not need to use it unless you copy an object of derived type, as in this example.
The compiler does not auto-generate constructors/operators unless they are used and no other constructor/operator can be used to do that operation (i.e. a copy operation can be used in some situations where a move operation would suffice). The latter statement results in the following set of rules.
Here are the rules to the auto-generation of certain member functions:
Default constructor (if no other constructor is explicitly declared)
Copy constructor if no move constructor or move assignment operator
is explicitly declared. If a destructor is declared generation of a
copy constructor is deprecated.
Move constructor if no copy
constructor, move assignment operator or destructor is explicitly
declared.
Copy assignment operator if no move constructor or move assignment
operator is explicitly declared. If a destructor is declared
generation of a copy assignment operator is deprecated.
Move assignment operator if no copy constructor, copy assignment operator
or destructor is explicitly declared.
Destructor
The list is taken from this Wikipedia page.
One class cannot call private methods on another class, but it can inherit as much as it is coded too. This code just includes the member functions from Uncopyable in Derived.
Imagine if you wrote a class inheriting from std::vector. You can still erase, insert, push_back and do all those sorts of things. Because these are all public or protected vector member functions, they in turn call implementation specific private functions that do the low level things like manage memory. Your code in this derived class couldn't call those memory management functions directly though. This is used to insure the creators of the vector can change the internal details freely without breaking your use of the class.
If your example is what the code actually looks like, then this it is a common pattern used to make things that cannot be copied. It would make code like the following produce a compiler error:
Derived Foo;
Derived Bar;
Foo = Bar
It would also make the code throw an error on the following:
int GetAnswer(Derived bar)
{ /* Do something with a Derived */ }
Derived Foo;
int answer = GetAnser(Foo);
This example fails because a copy of foo is made and passed as the parameter in the function GetAnswer.
There are many reasons why something might not be copyable. The most common I have experienced is that the object manages some low level resource a single file, an opengl context, an audio output, etc... Imagine if you had a class that managed a log file. If it closed the file in the deconstructor, what happens to the original when a copy is destroyed.
Edit: to pass an Uncopyable class to a function, pass it by reference. The Following function does not make a copy:
int GetAnswer(Derived& bar)
{ /* Do something with a Derived */ }
Derived Foo;
int answer = GetAnser(Foo);
It would also cause a compiler error if all the constructor were private and the class was instantiated. But even if all the member function even constructors were private and the class was never instantiated that would be valid compiling code.
Edit: The reason a class with constructor is that there maybe other way to construct it or it maybe have static member functions, or class functions.
Sometimes factories are used to build object which have no obvious constructor. These might have functions to whatever magic is required to make the umakeable class instance. The most common I have seen is just that there was another constructor that was public, but not in an obvious place. I have also seen factories as friend classes to the unconstructable class so they could call the constructors and I have seen code manually twiddle bits of memory and cast pointers to the memory it to an instance of a class. All of these patterns are used to insure that a class is correctly created beyond just the guarantees C++ supplies.
A more common pattern I have seen is static member functions in classes.
class uncreateable
{
uncreateable() {}
public:
static int GetImportantAnswer();
};
Looking at this it can be seen that not only do I not need to create a instance of the class to call GetImportantAnswer() but I couldn't create an instance if I wanted. I could call this code using the following:
int answer;
answer = uncreateable::GetImportantAnswer();
Edit: Spelling and grammar
Well, actually this program does not compile with g++:
#include <iostream>
using namespace std;
class Uncopyable{
public:
Uncopyable(){}
~Uncopyable(){}
private:
Uncopyable(const Uncopyable&) {cout<<"in parent copy constructor";}
Uncopyable& operator=(const Uncopyable&) { cout << "in parent assignment operator";}
};
class Derived: private Uncopyable{
};
int main() {
Derived a;
Derived b = a;
}
compiler output:
$ g++ 23183322.cpp
23183322.cpp:10:88: warning: control reaches end of non-void function [-Wreturn-type]
Uncopyable& operator=(const Uncopyable&) { cout << "in parent assignment operator";}
^
23183322.cpp:13:7: error: base class 'Uncopyable' has private copy constructor
class Derived: private Uncopyable{
^
23183322.cpp:9:5: note: declared private here
Uncopyable(const Uncopyable&) {cout<<"in parent copy constructor";}
^
23183322.cpp:19:15: note: implicit copy constructor for 'Derived' first required here
Derived b = a;
^
1 warning and 1 error generated.

Are constructors specified with the default keyword trivial?

I know that among other things, a trivial constructor has to be implicitly defined.
Does this also apply when we use the default keyword?
Say we specify a T()=default constructor , is it considered user-provided or is it treated like an implicit constructor?
Yes, a user-declared constructor that is defaulted on its first declaration may be trivial:
struct Foo
{
Foo() = default;
Foo(int, int);
char x;
};
#include <type_traits>
static_assert(std::is_trivially_constructible<Foo>::value, "Works");
The example demonstrates how to define a POD class even in the presence of user-defined (non-default) constructors.
From the standard (12.1), "a default constructor is trivial if it is not user-provided" (plus conditions), and (8.4.2):
A function is user-provided if it is user-declared and not explicitly defaulted or
deleted on its first declaration.
However, note that triviality of a default constructor depends on more than just its declaration and definition. To expand the quote from 12.1:
A default constructor is trivial if it is not user-provided and if:
— its class has no virtual functions (10.3) and no virtual base classes (10.1), and
— no non-static data member of its class has a brace-or-equal-initializer, and
— all the direct base classes of its class have trivial default constructors, and
— for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.
Implicit constructor is one provided by the compiler if you don't define one. That's a default constructor having no argument, unless you would like to have your own constructor with or without arguments to precisely control initialization of your object instance data members.

Is it true that a default constructor is synthesized for every class that does not define one?

If the class doesn't have the constructor, will the compiler make one default constructor for it ?
Programmers new to C++ often have two common misunderstandings:
That a default constructor is synthesized for every class that does
not define one
from the book Inside the C++ Object Model
I am at a loss...
This is well explained in the section from which this quote is taken. I will not paraphrase it in its entirety, but here is a short summary of the section content.
First of all, you need to understand the following terms: implicitly-declared, implicitly-defined, trivial, non-trivial and synthesized (a term that is used by Stanley Lippman, but is not used in the standard).
implicitly-declared
A constructor is implicitly-declared for a class if there is no user-declared constructor in this class. For example, this class struct T { }; does not declare any constructor, so the compiler implicitly declares a default constructor. On the other hand, this class struct T { T(int); }; declares a constructor, so the compiler will not declare an implicit default constructor. You will not be able to create an instance of T without parameters, unless you define your own default constructor.
implicitly-defined
An implicitly-declared constructor is implicitly-defined when it is used, i.e. when an instance is created without parameters. Assuming the following class struct T { };, the line T t; will trigger the definition of T::T(). Otherwise, you would have a linker error since the constructor would be declared but not defined. However, an implicitly-defined constructor does not necessarily have any code associated with it! A default constructor is synthesized (meaning that some code is created for it) by the compiler only under certain circumstances.
trivial constructor
An implicitly-declared default constructor is trivial when:
its class has no virtual functions and no virtual base classes and
its base classes have trivial constructors and
all its non-static members have trivial constructors.
In this case, the default compiler has nothing to do, so there is no code synthesized for it. For instance, in the following code
struct Trivial
{
int i;
char * pc;
};
int main()
{
Trivial t;
}
the construction of t does not involve any operations (you can see that by looking at the generated assembly: no constructor is called to construct t).
non-trivial
On the other hand, if the class does not meet the three requirements stated above, its implicitly-declared default constructor will be non-trivial, meaning that it will involve some operations that must be performed in order to respect the language semantics. In this case, the compiler will synthesize an implementation of the constructor performing these operations.
For instance, consider the following class:
struct NonTrivial
{
virtual void foo();
};
Since it has a virtual member function, its default constructor must set the virtual table pointer to the correct value (assuming the implementation use a virtual method table, of course).
Similarly, the constructor of this class
struct NonTrivial
{
std::string s;
};
must call the string default constructor, as it is not trivial. To perform these operations, the compiler generates the code for the default constructor, and calls it anytime you create an instance without parameters. You can check this by looking at the assembly corresponding to this instantiation NonTrivial n; (you should see a function call, unless the constructor has been inlined).
Summary
When you don't provide any constructor for your class, the compiler implicitly declares a default one. If you try to use it, the compiler implicitly defines it, if it can (it is not always possible, for instance when a class has a non-default-constructible member). However, this implicit definition does not imply the generation of any code. The compiler needs to generate code for the constructor (synthesize it) only if it is non-trivial, meaning that it involves certain operations needed to implement the language semantics.
N.B.
Stanley B Lippman's "Inside the C++ object model" and this answer deals with (a possible) implementation of C++, not its semantics. As a consequence, none of the above can be generalized to all compilers: as far as I know, an implementation is perfectly allowed to generate code even for a trivial constructor. From the C++ user point of view, all that matters is the "implicitly-declared/defined` aspect (and also the trivial/non-trivial distinction, as it has some implications (for instance, an object of a class with non-trivial constructor cannot be a member of a union)).
I think the misconception is:
That a default constructor is synthesized for every class that does not define one
That people think the default constructor, which accepts no arguments, will always be generated if you don't declare it yourself.
However, this is not true, because if you declare any constructor yourself, the default one will not be automatically created.
class MyClass {
public:
MyClass(int x) {}; // No default constructor will be generated now
};
This will lead to problems like when beginners expect to use MyClass like this:
MyClass mc;
Which won't work because there is no default constructor that accepts no args.
edit as OP is still a little confused.
Imagine that my MyClass above was this:
class MyClass {
};
int main() {
MyClass m;
}
That would compile, because the compiler will autogenerate the default constructor MyClass() because MyClass was used.
Now take a look at this:
#include <iostream>
class MyClass {
};
int main() {
std::cout << "exiting\n";
}
If this were the only code around, the compiler wouldn't even bother generating the default constructor, because MyClass is never used.
Now this:
#include <iostream>
class MyClass {
public:
MyClass(int x = 5) { _x = x; }
int _x;
};
int main() {
MyClass m;
std::cout << m._x;
}
The compiler doesn't generate default constructor MyClass(), because the class already has a constructor defined by me. This will work, and MyClass(int x = 5) works as your default constructor because it can accept no arguments, but it wasn't generated by the compiler.
And finally, where beginners might run into a problem:
class MyClass() {
public:
MyClass(int x) { _x = x; }
int _x;
};
int main() {
MyClass m;
}
The above will throw you an error during compilation, because MyClass m needs a default constructor (no arguments) to work, but you already declared a constructor that takes an int. The compiler will not generate a no-argument constructor in this situation either.
A default constructor is synthesized for every class that does not define one if:
The code using the class needs one & only if
There is no other constructor explicitly defined for the class by you.
All the upvoted answers thus far seem to say approximately the same thing:
A default constructor is synthesized for every class that does not have any user-defined constructor.
which is a modification of the statement in the question, which means
A default constructor is synthesized for every class that does not have a user-defined default constructor.
The difference is important, but the statement is still wrong.
A correct statement would be:
A default constructor is synthesized for every class that does not have any user-defined constructor and for which all sub-objects are default-constructible in the context of the class.
Here are some clear counter-examples to the first statement:
struct NoDefaultConstructor
{
NoDefaultConstructor(int);
};
class Surprise1
{
NoDefaultConstructor m;
} s1; // fails, no default constructor exists for Surprise1
class Surprise1 has no user-defined constructors, but no default constructor is synthesized.
It doesn't matter whether the subobject is a member or a base:
class Surprise2 : public NoDefaultConstructor
{
} s2; // fails, no default constructor exists for Surprise2
Even if all subobjects are default-constructible, the default constructor has to be accessible from the composite class:
class NonPublicConstructor
{
protected:
NonPublicConstructor();
};
class Surprise3
{
NonPublicConstructor m;
} s3; // fails, no default constructor exists for Surprise3
Yes a default constructor is always there by default if you don't define a constructor of your own (see the default constructor section here).
http://www.codeguru.com/forum/archive/index.php/t-257648.html
Quote:
The following sentense are got from the book "Inside the C++ object model" , written by Stanley B. Lippman.
There are four characteristics of a class under which the compiler
needs to synthesize a default constructor for classes that declare no
constructor at all. The Standard refers to these as implicit,
nontrivial default constructors. The synthesized constructor fulfills
only an implementation need. It does this by invoking member object or
base class default constructors or initializing the virtual function
or virtual base class mechanism for each object. Classes that do not
exhibit these characteristics and that declare no constructor at all
are said to have implicit, trivial default constructors. In practice,
these trivial default constructors are not synthesized. ...
Programmers new to C++ often have two common misunderstandings:
That a default constructor is synthesized for every class that does
not define one
That the compiler-synthesized default constructor provides explicit
default initializers for each data member declared within the class
As you have seen, neither of these is true.

MSVC9.0 bug or misunderstanding of virtual inheritance and friends?

consider the following code:
class A
{
friend class B;
friend class C;
};
class B: virtual private A
{
};
class C: private B
{
};
int main()
{
C x; //OK default constructor generated by compiler
C y = x; //compiler error: copy-constructor unavailable in C
y = x; //compiler error: assignment operator unavailable in C
}
The MSVC9.0 (the C++ compiler of Visual Studio 2008) does generate the default constructor but is unable to generate copy and assignment operators for C although C is a friend of A. Is this the expected behavior or is this a Microsoft bug? I think the latter is the case, and if I am right, can anyone point to an article/forum/... where this issue is discussed or where microsoft has reacted to this bug. Thank you in advance.
P.S. Incidentally, if BOTH private inheritances are changed to protected, everything works
P.P.S. I need a proof, that the above code is legal OR illegal. It was indeed intended that a class with a virtual private base could not be derived from, as I understand. But they seem to have missed the friend part. So... here it goes, my first bounty :)
The way I interpret the Standard, the sample code is well-formed. (And yes, the friend declarations make a big difference from the thing #Steve Townsend quoted.)
11.2p1: If a class is declared to be a base class for another class using the private access specifier, the public and protected members of the base class are accessible as private members of the derived class.
11.2p4: A member m is accessible when named in class N if
m as a member of N is public, or
m as a member of N is private, and the reference occurs in a member or friend of class N, or
m as a member of N is protected, and the reference occurs in a member or friend of class N, or in a member or friend of a class P derived from N, where m as a member of P is private or protected, or
there exists a base class B of N that is accessible at the point of reference, and m is accessible when named in class B.
11.4p1: A friend of a class is a function or class that is not a member of the class but is permitted to use the private and protected member names from the class.
There are no statements in Clause 11 (Member access control) which imply that a friend of a class ever has fewer access permissions than the class which befriended it. Note that "accessible" is only defined in the context of a specific class. Although we sometimes talk about a member or base class being "accessible" or "inaccessible" in general, it would be more accurate to talk about whether it is "accessible in all contexts" or "accessible in all classes" (as is the case when only public is used).
Now for the parts which describe checks on access control in automatically defined methods.
12.1p7: An implicitly-declared default constructor for a class is implicitly defined when it is used to create an object of its class type (1.8). The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with an empty mem-initializer-list (12.6.2) and an empty function body. If that user-written default constructor would be ill-formed, the program is ill-formed.
12.6.2p6: All sub-objects representing virtual base classes are initialized by the constructor of the most derived class (1.8). If the constructor of the most derived class does not specify a mem-initializer for a virtual base class V, then V's default constructor is called to initialize the virtual base class subobject. If V does not have an accessible default constructor, the initialization is ill-formed.
12.4p5: An implicitly-declared destructor is implicitly defined when it is used to destroy an object of its class type (3.7). A program is ill-formed if the class for which a destructor is implicitly defined has:
a non-static data member of class type (or array thereof) with an inaccessible destructor, or
a base class with an inaccessible destructor.
12.8p7: An implicitly-declared copy constructor is implicitly defined if it is used to initialize an object of its class type from a copy of an object of its class type or of a class type derived from its class type. [Note: the copy constructor is implicitly defined even if the implementation elided its use (12.2).] A program is ill-formed if the class for which a copy constructor is implicitly defined has:
a nonstatic data member of class type (or array thereof) with an inaccessible or ambiguous copy constructor, or
a base class with an inaccessible or ambiguous copy constructor.
12.8p12: A program is ill-formed if the class for which a copy assignment operator is implicitly defined has:
a nonstatic data member of const type, or
a nonstatic data member of reference type, or
a nonstatic data member of class type (or array thereof) with an inaccessible copy assignment operator, or
a base class with an inaccessible copy assignment operator.
All these requirements mentioning "inaccessible" or "accessible" must be interpreted in the context of some class, and the only class that makes sense is the one for which a member function is implicitly defined.
In the original example, class A implicitly has public default constructor, destructor, copy constructor, and copy assignment operator. By 11.2p4, since class C is a friend of class A, all those members are accessible when named in class C. Therefore, access checks on those members of class A do not cause the implicit definitions of class C's default constructor, destructor, copy constructor, or copy assignment operator to be ill-formed.
Your code compiles fine with Comeau Online, and also with MinGW g++ 4.4.1.
I'm mentioning that just an "authority argument".
From a standards POV access is orthogonal to virtual inheritance. The only problem with virtual inheritance is that it's the most derived class that initializes the virtually-derived-from class further up the inheritance chain (or "as if"). In your case the most derived class has the required access to do that, and so the code should compile.
MSVC also has some other problems with virtual inheritance.
So, yes,
the code is valid, and
it's an MSVC compiler bug.
FYI, that bug is still present in MSVC 10.0. I found a bug report about a similar bug, confirmed by Microsoft. However, with just some cursory googling I couldn't find this particular bug.
Classes with virtual private base should not be derived from, per this at the C++ SWG. The compiler is doing the right thing (up to a point). The issue is not with the visibility of A from C, it's that C should not be allowed to be instantiated at all, implying that the bug is in the first (default) construction rather than the other lines.
Can a class with a private virtual base class be derived from?
Section: 11.2 [class.access.base]
Status: NAD Submitter: Jason
Merrill Date: unknown
class Foo { public: Foo() {} ~Foo() {} };
class A : virtual private Foo { public: A() {} ~A() {} };
class Bar : public A { public: Bar() {} ~Bar() {} };
~Bar() calls
~Foo(), which is ill-formed due to
access violation, right? (Bar's
constructor has the same problem since
it needs to call Foo's constructor.)
There seems to be some disagreement
among compilers. Sun, IBM and g++
reject the testcase, EDG and HP accept
it. Perhaps this case should be
clarified by a note in the draft. In
short, it looks like a class with a
virtual private base can't be derived
from.
Rationale: This is what was intended.
btw the Visual C++ v10 compiler behaviour is the same as noted in the question. Removing virtual from the inheritance of A in B fixes the problem.