I know that following code gives compilation error :
class A{ public : virtual void name(){cout<<typeid(this).name()<<endl;}; };
class B:protected A{public : virtual void name(){cout<<typeid(this).name()<<endl;};};
void foo(B* b)
{
A * a = dynamic_cast<A*>(b); //Error : 'A' is an inaccessible base of 'B'
return;
}
But then why in the C++ Stroustrup book (15.4.1) he writes
class BB_ival_slider:public Ival_slider,protected BBslider{ //...
};
void f(BB_ival_slider*p)
{
// ok
BBslider* pbb2 = dynamic_cast<BBslider*>(p); // ok: pbb2 becomes 0
}
Shouldn't the line be compilation error ?
So either my gcc is wrong in flagging it as compilation error OR the unthinkable, stroustrup typo or most plausibly I have missed something...
The actual quote from 15.4.1 is:
class BB_ival_slider : public Ival_slider, protected BBslider {
// ...
};
void f(BB_ival_slider* p)
{
Ival_slider* pi1 = p; // ok
Ival_slider* pi2 = dynamic_cast<Ival_slider*>(p); // ok
BBslider* pbb1 = p; // error: BBslider is a protected base
BBslider* pbb2 = dynamic_cast<BBslider*>(p); // ok: pbb2 becomes 0
}
That is the uninteresting case. However, it is reassuring to know that dynamic_cast doesn't allow accidental violation of the protection of private and protected base classes.
So it would seem that the text describing the code is correct, but for the wrong reasons -- dynamic_cast doesn't allow accidental violation of the protection of private and protected base classes, but only because using it would be ill-formed and will result in a compiler error, not because using it will yield a null-pointer. And, of course, the code the text is describing is definitely incorrect.
Mistakes happen -- maybe it will be fixed in the 4th edition of the book. :-]
(Also, note that if BB_ival_slider declares f to be a friend, then the code will behave as described in the book. Perhaps this friend declaration was implied earlier in the chapter, but I don't have time right now to read over it carefully to check one way or the other.)
Perhaps he tested that code, perhaps not. (Lots of authors put untested code in their books.) If he did test it, keep in mind that not all compilers are created equal. g++ fails with error: 'BBslider' is an inaccessible base of 'BB_ival_slider'. clang fails with error: cannot cast 'BB_ival_slider' to its protected base class 'BBslider'. Other compilers: Who knows? Every compiler I know of has some problem with compliance with the standard.
I think if I am not finding any constructive evidence then I might just say
"Stroustrup was wrong" (that sounds scary :( )
I dont think compilers are allowed to spill the guts of class internal willingly(by defined standard). Unless they are put through knife. (evil pointer operation that is)
Related
Recently, I came across code like this:
class NeedsFactoryForPublicCreation
{
private:
struct Accessor
{
// Enable in order to make the compile failing (expected behavior)
// explicit Accessor() = default;
};
public:
explicit NeedsFactoryForPublicCreation(Accessor) {}
// This was intended to be the only public construction way
static NeedsFactoryForPublicCreation create()
{
NeedsFactoryForPublicCreation result{Accessor()};
// ... Do something (complex parametrization) further on
return result;
}
};
int main()
{
//NeedsFactoryForPublicCreation::Accessor publicAccessor {}; // Does not compile as expected
NeedsFactoryForPublicCreation nonDefaultConstructible {{}}; // Compiles even with Accessor being an interal
}
At first, I was a bit shocked, that this compiles.
After some minutes of analysis (and occurring self-doubts...), I found out, that this is fully explainable due to the definition of access specifiers and the way the compiler decides what actual way of initialization is used (aggregate vs. public constructor look-up). In order to extend the first confusion, even this access class compiles this way:
class Accessor
{
Accessor() = default; // private, but we are an aggregate...
friend class NeedsFactoryForPublicCreation;
};
which is again fully explainable since Accessor is still an aggregate (another confusing topic...).
But in order to emphasize, that this question has nothing to do with aggregates in detail (thanks to Jarod42 in the comments to point out the upcoming C++20 changes here!), this compiles too:
class Accessor
{
public:
Accessor() {}
virtual ~Accessor() {}
virtual void enSureNonAggregate() const {}
friend class NeedsFactoryForPublicCreation;
};
and does not as soon as the constructor becomes private.
My question: What's the actual background, the standard decided the effect of access specifiers this counterintuitively in doubt? With counterintuitively I especially mean the inconsistency of effective look-up (the compiler doesn't care about the internal as long as we stay unnamed, but then cares when it comes to actual constructor look-up, still fully unnamed context). Or maybe I'm mixing categories too much here.
I know, access specifiers' background is quite strictly naming based and there are also other ways to achieve the "publication" of this internal, but as far as I know, they are far more explicit. Legally implicitly creating an unnamed temporary of a private internal within an outer scope via this extremely implicit way looks horrible and might even be quite error prone, at latest when multiple arguments are the case (uniform initialized empty std-containers...).
The code as follows:
#include <iostream>
struct A {
virtual void foo() { std::cout << "hello world!" << std::endl; }
};
struct B : public A {
void foo() override { base:foo(); }
};
void main() {
A* p = new B();
p->foo();
delete p;
}
what is the 'base:' means? is it a standard key word in c++?
platform: win10 + vs2015 update3;
project type: win32 console project;
A somewhat known idiom would involve something like
struct B : public A {
typedef A base;
void foo() override { base::foo(); }
};
What you have there looks superficially similar, but it is not that. In your case base: is just a label, which affects nothing. Unless the code you presented is an intentional puzzle/joke, it might actually be an attempt to reproduce what I posted above by a person who just doesn't rememebr all the details.
In any case, base is not a keyword in C++ (and is not a keyword in VS2015 either).
base is not a keyword in C++. It's just an ordinary identifier with no special meaning.
If the code is exactly what you've shown us, then the base: is a goto label -- and completely pointless, since there are no references to it. You can demonstrate this yourself by (temporarily) adding goto base; after base:foo();. (I just tried it myself and didn't get any additional diagnostics. Of course that would be an infinite loop.)
It's likely that the author of the code didn't intend it to be a goto label, and might have thought that base would refer to the parent class. Perhaps base: was a typo for base:: (which would be an error -- perhaps base is a keyword in some other language)?
It's impossible to be sure what the author intended. The use of void main(), which is illegal in C++ (it needs to be int main()) suggests that the author doesn't know C++ very well. He or she probably tried to do something that refers to the parent class, wrote it incorrectly, and happened by chance to write something that happens to compile.
In the below code, there are two "equivalent" calls to std::for_each using boost:bind expressions. The indicated line compiles, the indicated failing line fails. The best explanation I can find in the standard amounts to "because we said so". I'm looking for "why the standard indicates this behavior". My suppositions are below.
My question is simply: Why does the indicated line compile and the equivalent following line fail to compile (and I don't want because "the standard says so", I already know that - I will not accept any answers that give this as an explanation; I'd like an explanation as to why the standard says so).
Notes: Although I use boost, boost is irrelevant to this question, and the error in various formats has been reproduced using g++ 4.1.* and VC7.1.
#include <boost/bind.hpp>
#include <iostream>
#include <map>
#include <algorithm>
class Base
{
protected:
void foo(int i)
{ std::cout << "Base: " << i << std::endl; }
};
struct Derived : public Base
{
Derived()
{
data[0] = 5;
data[1] = 6;
data[2] = 7;
}
void test()
{
// Compiles
std::for_each(data.begin(), data.end(),
boost::bind(&Derived::foo, this,
boost::bind(&std::map<int, int>::value_type::second, _1)));
// Fails to compile - why?
std::for_each(data.begin(), data.end(),
boost::bind(&Base::foo, this,
boost::bind(&std::map<int, int>::value_type::second, _1)));
}
std::map<int, int> data;
};
int main(int, const char**)
{
Derived().test();
return 0;
}
The indicated line fails with this error:
main.C: In member function 'void Derived::test()':
main.C:9: error: 'void Base::foo(int)' is protected
main.C:31: error: within this context
As noted, the supposedly equivalent statement above compiles cleanly (and if the offending statement is commented out, runs with the expected result of printing “5”, “6”, “7” on separate lines).
While searching for an explanation, I came across 11.5.1 in the standard (specifically, I’m looking at the 2006-11-06 draft):
An additional access check beyond
those described earlier in clause 11
is applied when a non-static data
member or nonstatic member function is
a protected member of its naming class
(11.2)105) As described earlier,
access to a protected member is
granted because the reference occurs
in a friend or member of some class C.
If the access is to form a pointer to
member (5.3.1), the
nested-name-specifier shall name C or
a class derived from C. All other
accesses involve a (possibly implicit)
object expression (5.2.5). In this
case, the class of the object
expression shall be C or a class
derived from C.
After reading this, it became evidently why the second statement failed while the first succeeded, but then the question came up: What is the rationale for this?
My initial thought was that the compiler was expanding the boost::bind templates, discovering that Base::foo was protected and kicking it out because boost::bind<…> was not a friend. But, the more I thought about this explanation, the less it made sense, because if I recall correctly, as soon as you take the pointer to a member (assuming you initially are within access control of the member), all access control information is lost (i.e. I could define a function that returns an arbitrary pointer to a member that alternately returns a public, protected or private member depending on some input and the returner would be none the wiser).
More I thought about it, and the only plausible explanation I could come up with why it should make a difference was in the case of multiple inheritance. Specifically, that depending on the class layout, the member pointer when calculated from Base would be different than that calculated from Derived.
It's all about "context". In the first call the context of the call is Derived which has access to the protected members of Base and hence is allowed to take addresses of them. In the second the context is "outside of" Derived and hence outside of Base so the protected member access is not allowed.
Actually, this seems logical. Inheritance gives you access to Derived::foo and not to Base::foo. Let me illustrate with a code example:
struct Derived : public Base
{
void callPrivateMethod(Base &b)
{
// this should obviously fail
b.foo(5);
// pointer-to-member call should also fail
void (Base::*pBaseFoo) (int) = &Base::foo; // the same error as yours here
(b.*pBaseFoo)(5);
}
};
The reason for this restriction is enforcement of access control across different classes that share a common base.
This is reinforced by notes in Core Language Defects Report defect #385, the relevant part copied here for reference:
[...] the reason we have this rule is that C's use of inherited protected members might be different from their use in a sibling class, say D. Thus members and friends of C can only use B::p in a manner consistent with C's usage, i.e., in C or derived-from-C objects.
As an example of something this rule prevents:
class B {
protected:
void p() { };
};
class C : public B {
public:
typedef void (B::*fn_t)();
fn_t get_p() {
return &B::p; // compilation error here, B::p is protected
}
};
class D : public B { };
int main() {
C c;
C::fn_t pbp = c.get_p();
B * pb = new D();
(pb->*pbp)();
}
The protected status of D::p is something we want the compiler to enforce, but if the above compiled that would not be the case.
I just wanted to know whether is this following block of code fully valid in C++:
class A
{
public:
virtual bool b() = 0;
};
class B
{
public:
virtual bool b() = 0;
};
class C: public A, public B
{
public:
virtual bool A::b()
{
return true;
}
virtual bool B::b()
{
return false;
}
};
Using VS2008 it compiles without any errors, however, on GCC (MinGW) 3.4.5 it gives me errors like:
cannot declare member function `A::b' within `C'
On the lines where the virtual methods are implemented. I was curious if this is just generally considered invalid and by C++ standards forbidden code (and in VS it thus works thanks to some MS non-standardized magic), or only a bug or unsupported language feature in GCC.
No it's not valid. You can't override them separately like that, because they would have the same signature.
There is a guru of the week about that.
The qualified name A::b is not allowed as the name of a member of class C.
It should not compile due to parents having the same function name. Furthermore, you aren't suppose to overload the function b more than once.
If you refer to the virtual table created for this:
0(beginning of vtable) - A::b() -> B::b()
You see, since class B has the same function name as class A, it overrides it, thus you have now B::b() to override (since it's still pure). This is due to multiple inheritancy. How would the compiler be able to differenciate between the two (they have the same signature)? Generally, this will fail, because like I just said, the compiler isn't suppose to make decisions, it's supposed to tell you that there is a problem.
It compiles on VS, but have you tried running it (included in a file where it is actually created)? Sometimes, compiler are lazy and don't pop errors on classes that aren't used.
Just as an FYI, VC gives the error only when you try to use the b method:
C:\temp\test.cpp(33) : error C2668: 'C::b' : ambiguous call to overloaded function
C:\temp\test.cpp(23): could be 'bool C::b(void)'
C:\temp\test.cpp(18): or 'bool C::b(void)'
while trying to match the argument list '(void)'
And for what it's worth, Comeau's compiler behaves similarly, but with an even more confusing error message:
"C:\temp\test.cpp", line 33: error: no instance of overloaded function "C::b"
matches the argument list
object type is: C
bool z = c.b();
Is there a side effect in doing this:
C code:
struct foo {
int k;
};
int ret_foo(const struct foo* f){
return f.k;
}
C++ code:
class bar : public foo {
int my_bar() {
return ret_foo( (foo)this );
}
};
There's an extern "C" around the C++ code and each code is inside its own compilation unit.
Is this portable across compilers?
This is entirely legal. In C++, classes and structs are identical concepts, with the exception that all struct members are public by default. That's the only difference. So asking whether you can extend a struct is no different than asking if you can extend a class.
There is one caveat here. There is no guarantee of layout consistency from compiler to compiler. So if you compile your C code with a different compiler than your C++ code, you may run into problems related to member layout (padding especially). This can even occur when using C and C++ compilers from the same vendor.
I have had this happen with gcc and g++. I worked on a project which used several large structs. Unfortunately, g++ packed the structs significantly looser than gcc, which caused significant problems sharing objects between C and C++ code. We eventually had to manually set packing and insert padding to make the C and C++ code treat the structs the same. Note however, that this problem can occur regardless of subclassing. In fact we weren't subclassing the C struct in this case.
I certainly not recommend using such weird subclassing. It would be better to change your design to use composition instead of inheritance.
Just make one member
foo* m_pfoo;
in the bar class and it will do the same job.
Other thing you can do is to make one more class FooWrapper, containing the structure in itself with the corresponding getter method. Then you can subclass the wrapper. This way the problem with the virtual destructor is gone.
“Never derive from concrete classes.” — Sutter
“Make non-leaf classes abstract.” — Meyers
It’s simply wrong to subclass non-interface classes. You should refactor your libraries.
Technically, you can do what you want, so long as you don’t invoke undefined behavior by, e. g., deleting a pointer to the derived class by a pointer to its base class subobject. You don’t even need extern "C" for the C++ code. Yes, it’s portable. But it’s poor design.
This is perfectly legal, though it might be confusing for other programmers.
You can use inheritance to extend C-structs with methods and constructors.
Sample :
struct POINT { int x, y; }
class CPoint : POINT
{
public:
CPoint( int x_, int y_ ) { x = x_; y = y_; }
const CPoint& operator+=( const POINT& op2 )
{ x += op2.x; y += op2.y; return *this; }
// etc.
};
Extending structs might be "more" evil, but is not something you are forbidden to do.
Wow, that's evil.
Is this portable across compilers?
Most definitely not. Consider the following:
foo* x = new bar();
delete x;
In order for this to work, foo's destructor must be virtual which it clearly isn't. As long as you don't use new and as long as the derived objectd don't have custom destructors, though, you could be lucky.
/EDIT: On the other hand, if the code is only used as in the question, inheritance has no advantage over composition. Just follow the advice given by m_pGladiator.
This is perfectly legal, and you can see it in practice with the MFC CRect and CPoint classes. CPoint derives from POINT (defined in windef.h), and CRect derives from RECT. You are simply decorating an object with member functions. As long as you don't extend the object with more data, you're fine. In fact, if you have a complex C struct that is a pain to default-initialize, extending it with a class that contains a default constructor is an easy way to deal with that issue.
Even if you do this:
foo *pFoo = new bar;
delete pFoo;
then you're fine, since your constructor and destructor are trivial, and you haven't allocated any extra memory.
You also don't have to wrap your C++ object with 'extern "C"', since you're not actually passing a C++ type to the C functions.
I don't think it is necessarily a problem. The behaviour is well defined, and as long as you are careful with life-time issues (don't mix and match allocations between the C++ and C code) will do what you want. It should be perfectly portable across compilers.
The problem with destructors is real, but applies any time the base class destructor isn't virtual not just for C structs. It is something you need to be aware of but doesn't preclude using this pattern.
It will work, and portably BUT you cannot use any virtual functions (which includes destructors).
I would recommend that instead of doing this you have Bar contain a Foo.
class Bar
{
private:
Foo mFoo;
};
I don't get why you don't simply make ret_foo a member method. Your current way makes your code awfully hard to understand. What is so difficult about using a real class in the first place with a member variable and get/set methods?
I know it's possible to subclass structs in C++, but the danger is that others won't be able to understand what you coded because it's so seldom that somebody actually does it. I'd go for a robust and common solution instead.
It probably will work but I do not believe it is guaranteed to. The following is a quote from ISO C++ 10/5:
A base class subobject might have a layout (3.7) different from the layout of a most derived object of the same type.
It's hard to see how in the "real world" this could actually be the case.
EDIT:
The bottom line is that the standard has not limited the number of places where a base class subobject layout can be different from a concrete object with that same Base type. The result is that any assumptions you may have, such as POD-ness etc. are not necessarily true for the base class subobject.
EDIT:
An alternative approach, and one whose behaviour is well defined is to make 'foo' a member of 'bar' and to provide a conversion operator where it's necessary.
class bar {
public:
int my_bar() {
return ret_foo( foo_ );
}
//
// This allows a 'bar' to be used where a 'foo' is expected
inline operator foo& () {
return foo_;
}
private:
foo foo_;
};