Why should I use the using keyword to access my base class method?
The action
declared in the derived class hides the action
declared in the base class. If you use action
on a Son
object the compiler will search in the methods declared in Son
, find one called action
, and use that. It won't go on to search in the base class's methods, since it already found a matching name.
Then that method doesn't match the parameters of the call and you get an error.
See also the C++ FAQ for more explanations on this topic.
using keyword for base class variable
Generic programming is slightly different from object oriented programming.
Your mTuple
is an example of a nondependent name. As far as the compiler is concerned, at the time the template definition is processed the compiler doesn't know that the class template has inherited a data member named mTuple
. It might be obvious to you, but it is not obvious to the compiler. At this stage, the compiler is oblivious to the obvious.
If the methods of the derived class template wish to use some member of the parent class template, the compiler needs to be explicitly told to do so. Hence the using
.
Edit
The above was a bit terse. It is important to remember that those class templates are not classes. They are templates that eventually define a class. Up until the moment that the class template is used to define a class that class template isn't quite real. More importantly, for a class template that inherits from some other class template, that inheritance isn't quite real. The compiler doesn't know about that inheritance unless it is explicitly told about it. That's why you will see derived class templates import the parent class's members via using ParentClass<Type>::member
(for example).
Edit #2
Marshall Cline discusses this topic in his C++-FAQ at http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19
Edit #3
(Per request) Just because some code compiles on your compiler does not mean it compiles on every compiler (for the same language). Compiler vendors add their own 'features' to a language, sometimes very intentionally, sometimes just because the vendors themselves goofed up, and sometimes because the standard itself is buggy. This issue of not-quite-standard compilers has been a problem for a long time, with many languages. The problem apparently is quite rampant when it comes to generic programming.
You can do everything right (or so you think): Turn on all standard warnings and then some, run your code through some commercial code analyzer, and you still might not have portable code.
Why does calling a method in my derived class call the base class method?
There's a difference between new
and virtual
/override
.
You can imagine, that a class, when instantiated, is nothing more than a table of pointers, pointing to the actual implementation of its methods. The following image should visualize this pretty well:
Now there are different ways, a method can be defined. Each behaves different when it is used with inheritance. The standard way always works like the image above illustrates. If you want to change this behavior, you can attach different keywords to your method.
1. Abstract classes
The first one is abstract
. abstract
methods simply point to nowhere:
If your class contains abstract members, it also needs to be marked as abstract
, otherwise the compiler will not compile your application. You cannot create instances of abstract
classes, but you can inherit from them and create instances of your inherited classes and access them using the base class definition. In your example this would look like:
public abstract class Person
{
public abstract void ShowInfo();
}
public class Teacher : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a teacher!");
}
}
public class Student : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a student!");
}
}
If called, the behavior of ShowInfo
varies, based on the implementation:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a student!'
Both, Student
s and Teacher
s are Person
s, but they behave different when they are asked to prompt information about themselves. However, the way to ask them to prompt their information, is the same: Using the Person
class interface.
So what happens behind the scenes, when you inherit from Person
? When implementing ShowInfo
, the pointer is not pointing to nowhere any longer, it now points to the actual implementation! When creating a Student
instance, it points to Student
s ShowInfo
:
2. Virtual methods
The second way is to use virtual
methods. The behavior is the same, except you are providing an optional default implementation in your base class. Classes with virtual
members can be instanciated, however inherited classes can provide different implementations. Here's what your code should actually look like to work:
public class Person
{
public virtual void ShowInfo()
{
Console.WriteLine("I am a person!");
}
}
public class Teacher : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a teacher!");
}
}
The key difference is, that the base member Person.ShowInfo
isn't pointing to nowhere any longer. This is also the reason, why you can create instances of Person
(and thus it does not need to be marked as abstract
any longer):
You should notice, that this doesn't look different from the first image for now. This is because the virtual
method is pointing to an implementation "the standard way". Using virtual
, you can tell Persons
, that they can (not must) provide a different implementation for ShowInfo
. If you provide a different implementation (using override
), like I did for the Teacher
above, the image would look the same as for abstract
. Imagine, we did not provide a custom implementation for Student
s:
public class Student : Person
{
}
The code would be called like this:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a person!'
And the image for Student
would look like this:
3. The magic `new` keyword aka "Shadowing"
new
is more a hack around this. You can provide methods in generalized classes, that have the same names as methods in the base class/interface. Both point to their own, custom implementation:
The implementation looks like the one, you provided. The behavior differs, based on the way you access the method:
Teacher teacher = new Teacher();
Person person = (Person)teacher;
teacher.ShowInfo(); // Prints 'I am a teacher!'
person.ShowInfo(); // Prints 'I am a person!'
This behavior can be wanted, but in your case it is misleading.
I hope this makes things clearer to understand for you!
What really is the purpose of base keyword in c#?
The base
keyword is used to refer to the base class when chaining constructors or when you want to access a member (method, property, anything) in the base class that has been overridden or hidden in the current class. For example,
class A {
protected virtual void Foo() {
Console.WriteLine("I'm A");
}
}
class B : A {
protected override void Foo() {
Console.WriteLine("I'm B");
}
public void Bar() {
Foo();
base.Foo();
}
}
With these definitions,
new B().Bar();
would output
I'm B
I'm A
Should the base Keyword be used?
You should not use base
unless you specifically mean "Even if there is a method in this class that overrides the base implementation, I want to call the base implementation and ignore the one on this class".
Using base
bypasses the virtual dispatch mechanism that is so important in polymorphism by causing a call
instruction to be emitted rather than callvirt
.
So saying base.Foo()
is very, very different in semantics to saying this.Foo()
. And you almost always want the latter.
Should I use virtual, override, or both keywords?
When you override a function you don't technically need to write either virtual
or override
.
The original base class declaration needs the keyword virtual
to mark it as virtual.
In the derived class the function is virtual by way of having the ¹same type as the base class function.
However, an override
can help avoid bugs by producing a compilation error when the intended override isn't technically an override. For instance, the function type isn't exactly like the base class function. Or that a maintenance of the base class changes that function's type, e.g. adding a defaulted argument.
In the same way, a virtual
keyword in the derived class can make such a bug more subtle by ensuring that the function is still virtual in the further derived classes.
So the general advice is,
Use
virtual
for the base class function declaration.
This is technically necessary.Use
override
(only) for a derived class' override.
This helps maintenance.
Example:
struct Base { virtual void foo() {} };
struct Derived: Base { void foo() override {} };
Notes:
¹ C++ supports covariant raw pointer and raw reference results. With covariance the type of the override isn't exactly the same. It just has a compatible type.
C++ keyword using
See this
Why should I use the "using" keyword to access my base class method?
Also this
using
The using keyword is used to import a
namespace (or parts of a namespace)
into the current scope. Example code:
For example, the following code
imports the entire std namespace into
the current scope so that items within
that namespace can be used without a
preceeding “std::”.using namespace std;
Alternatively, the next code snippet
just imports a single element of the
std namespace into the current
namespace:using std::cout;
Related Topics: namespace
Using is for namespace specifications/use - not as I think you are trying to use it.
Related Topics
How to Use Boost Bind with a Member Function
"String Could Not Resolved" Error in Eclipse for C++ (Eclipse Can't Resolve Standard Library)
Checking a Member Exists, Possibly in a Base Class, C++11 Version
Convert String Containing Several Numbers into Integers
Order of Evaluation of Elements in List-Initialization
How to Find the Actual Path Found by Bfs
Random Array Generation with No Duplicates
How to Correctly and Standardly Compare Floats
Why Catch an Exception as Reference-To-Const
Why Can't Static_Cast Be Used to Down-Cast When Virtual Inheritance Is Involved
Difference in Performance Between Msvc and Gcc for Highly Optimized Matrix Multplication Code
Taking the Address of a Temporary Object
When Is a C++ Destructor Called
/Usr/Lib/X86_64-Linux-Gnu/Libstdc++.So.6: Version Cxxabi_1.3.8' Not Found
G++ "Calling" a Function Without Parenthesis (Not F() But F; ). Why Does It Always Return 1