using namespace std;
class a
{
public:
a();
~a();
virtual int fat(int x);
};
a::a()
{
cout << "constructor a\n";
}
a::~a()
{
cout << "destructor a\n";
}
int a::fat(int x)
{
cout << "fat a\n";
return 1;
}
class b : public a
{
public:
b();
~b();
int fat(double y);
};
b::b()
{
cout << "constructor b\n";
}
b::~b()
{
cout << "destructor b\n";
}
int b::fat(double y)
{
cout << "in fat b\n"; return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
b me;
me.fat((int) 1);
return 0;
}
C++ inheritance all frelled up!..
Why does this print "in fat b" versus "fat a"?
"frelled" huh. I see.
Well the reason is one takes a double and one takes a float, so you actually aren't overloading via inheritence, you're doing plain old function overloading based on type. Because they take different parameters, they both exist at once.
If you cast it to a double, it would probably run fat a.
EDIT: Barius got there first, and was far more concise. [wink]
Well the reason is one takes a double and one takes a float, so you actually aren't overloading via inheritence, you're doing plain old function overloading based on type. Because they take different parameters, they both exist at once.
If you cast it to a double, it would probably run fat a.
EDIT: Barius got there first, and was far more concise. [wink]
You should use a virtual destructor for a. Otherwise this won't work right:
a* x = new b;
delete x;
it would only call a's destructor, not b's even though the object is of type b.
a* x = new b;
delete x;
it would only call a's destructor, not b's even though the object is of type b.
You guys missed the point:
The function int fat(double y); in b hides the function virtual int fat(int x); in a, so when you call fat on an object of type b, only the functio ntaking a double is visiable, so the int gets converted to a double.
To have this work you need to change the declaration of b to:
Quote:
Why does this print "in fat b" versus "fat a"?
The function int fat(double y); in b hides the function virtual int fat(int x); in a, so when you call fat on an object of type b, only the functio ntaking a double is visiable, so the int gets converted to a double.
To have this work you need to change the declaration of b to:
class b : public a{public: b(); ~b(); int fat(double y); using a::fat;//make a::fat visible here.};
Quote:Original post by Nitage
You guys missed the point:Quote:
Why does this print "in fat b" versus "fat a"?
The function int fat(double y); in b hides the function virtual int fat(int x); in a, so when you call fat on an object of type b, only the functio ntaking a double is visiable, so the int gets converted to a double.
To have this work you need to change the declaration of b to:
*** Source Snippet Removed ***
Err no it doesn't, the functions have different signatures
me.fat((double) 1); // calls fat a
Quote:Original post by paulecoyote
Err no it doesn't, the functions have different signatures
Umm, yes it does. Read the holy standard.
Despite casting the argument to an int, it gets reconverted back to a double because the fat() function in class b hoides the fat() function in class a. If the OP added a "using a::fat" in his class b definition, the class a fat() would be hoisted into class b.
alrighty, hands up, I was wrong on that. [rolleyes]
You know, in over 8 years of C++ I've never had to use the using keyword like that in any of my class structures. I've used it with namespaces, but not to force declare things in class scope.
EDIT:
Although I think I might have used it to fudge something when writing a template actually come to think of it.
Learn something new everyday I guess.
It seems kind of messy to me, like something you could do, but not necessarily should do.
You know, in over 8 years of C++ I've never had to use the using keyword like that in any of my class structures. I've used it with namespaces, but not to force declare things in class scope.
EDIT:
Although I think I might have used it to fudge something when writing a template actually come to think of it.
Learn something new everyday I guess.
It seems kind of messy to me, like something you could do, but not necessarily should do.
From MSDN
The using declaration introduces a name into the declarative region in which the using declaration appears.using [typename][::] nested-name-specifier unqualified-idusing :: unqualified-id
Remarks
The name becomes a synonym for an entity declared elsewhere. It allows an individual name from a specific namespace to be used without explicit qualification. This is in contrast to the using directive, which allows all the names in a namespace to be used without qualification. See using Directive for more information.
Example
A using declaration can be used in a class definition.// using_declaration1.cpp#include <stdio.h>class B {public: void f(char) { printf_s("In B::f()\n"); } void g(char) { printf_s("In B::g()\n"); }};class D : B {public: using B::f; using B::g; void f(int) { printf_s("In D::f()\n"); f('c'); } void g(int) { printf_s("In D::g()\n"); g('c'); }};int main() { D myD; myD.f(1); myD.g('a');}
Output
In D::f()
In B::f()
In B::g()
When used to declare a member, a using declaration must refer to a member of a base class.// using_declaration2.cpp#include <stdio.h>class B {public: void f(char) { printf_s("In B::f()\n"); } void g(char) { printf_s("In B::g()\n"); }};class C {public: int g();};class D2 : public B {public: using B::f; // ok: B is a base of D2 // using C::g; // error: C isn't a base of D2};int main() { D2 MyD2; MyD2.f('a');}
Output
In B::f()
Members declared with a using declaration can be referenced using explicit qualification. The :: prefix refers to the global namespace.// using_declaration3.cpp#include <stdio.h>void f() { printf_s("In f\n");}namespace A { void g() { printf_s("In A::g\n"); }}namespace X { using ::f; // global f using A::g; // A's g}void h() { printf_s("In h\n"); X::f(); // calls ::f X::g(); // calls A::g}int main() { h();}
Output
In h
In f
In A::g
When a using declaration is made, the synonym created by the declaration refers only to definitions that are valid at the point of the using declaration. Definitions added to a namespace after the using declaration are not valid synonyms.
A name defined by a using declaration is an alias for its original name. It does not affect the type, linkage or other attributes of the original declaration.// post_declaration_namespace_additions.cpp// compile with: /cnamespace A { void f(int) {}}using A::f; // f is a synonym for A::f(int) onlynamespace A { void f(char) {}}void f() { f('a'); // refers to A::f(int), even though A::f(char) exists}void b() { using A::f; // refers to A::f(int) AND A::f(char) f('a'); // calls A::f(char);}
With respect to functions in namespaces, if a set of local declarations and using declarations for a single name are given in a declarative region, they must all refer to the same entity, or they must all refer to functions.// functions_in_namespaces1.cpp// C2874 expectednamespace B { int i; void f(int); void f(double);}void g() { int i; using B::i; // error: i declared twice void f(char); using B::f; // ok: each f is a function}
In the example above, the using B::i statement causes a second int i to be declared in the g() function. The using B::f statement does not conflict with the f(char) function because the function names introduced by B::f have different parameter types.
A local function declaration cannot have the same name and type as a function introduced by using declaration. For example:// functions_in_namespaces2.cpp// C2668 expectednamespace B { void f(int); void f(double);}namespace C { void f(int); void f(double); void f(char);}void h() { using B::f; // introduces B::f(int) and B::f(double) using C::f; // C::f(int), C::f(double), and C::f(char) f('h'); // calls C::f(char) f(1); // C2668 ambiguous: B::f(int) or C::f(int)? void f(int); // C2883 conflicts with B::f(int) and C::f(int)}
With respect to inheritance, when a using declaration introduces a name from a base class into a derived class scope, member functions in the derived class override virtual member functions with the same name and argument types in the base class.// using_declaration_inheritance1.cpp#include <stdio.h>struct B { virtual void f(int) { printf_s("In B::f(int)\n"); } virtual void f(char) { printf_s("In B::f(char)\n"); } void g(int) { printf_s("In B::g\n"); } void h(int);};struct D : B { using B::f; void f(int) { // ok: D::f(int) overrides B::f(int) printf_s("In D::f(int)\n"); } using B::g; void g(char) { // ok: there is no B::g(char) printf_s("In D::g(char)\n"); } using B::h; void h(int) {} // Note: D::h(int) hides non-virtual B::h(int)};void f(D* pd) { pd->f(1); // calls D::f(int) pd->f('a'); // calls B::f(char) pd->g(1); // calls B::g(int) pd->g('a'); // calls D::g(char)}int main() { D * myd = new D(); f(myd);}
Output
In D::f(int)
In B::f(char)
In B::g
In D::g(char)
All instances of a name mentioned in a using declaration must be accessible. In particular, if a derived class uses a using declaration to access a member of a base class, the member name must be accessible. If the name is that of an overloaded member function, then all functions named must be accessible.
See Member-Access Control, for more information on accessibility of members.// using_declaration_inheritance2.cpp// C2876 expectedclass A {private: void f(char);public: void f(int);protected: void g();};class B : public A { using A::f; // C2876: A::f(char) is inaccessiblepublic: using A::g; // B::g is a public synonym for A::g};
Quote:Original post by paulecoyote
alrighty, hands up, I was wrong on that. [rolleyes]
You know, in over 8 years of C++ I've never had to use the using keyword like that in any of my class structures. I've used it with namespaces, but not to force declare things in class scope.
That's because sane people don't usually end up creating this situation for themselves. Seriously - if bs can fat() with doubles as well as they do with ints, why shouldn't any other as be able to do so? Derived-class-specific functionality normally demands a new function name.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement