Which public function is called when referenced in superclass constructor? - c++

I was wondering about an issue of execution order: if I have a class whose constructor calls a function f() of itself and then make a subclass which overrides that function and calls the superclass' constructor, which f() is executed?
To answer this question, I wrote this program:
#include <iostream>
using namespace std;
class Super
{
public:
Super();
void
f();
};
class Sub : public Super
{
public:
Sub();
void
f();
};
Super::Super()
{
this->f();
}
void
Super::f()
{
cout << "hello" << endl;
}
Sub::Sub()
: Super()
{
}
void
Sub::f()
{
cout << "world" << endl;
}
int
main()
{
Super super();
Sub sub();
sub.f();
return 0;
}
Originally, I did not include the sub.f() call in main(), but the program did nothing but exit with code 0, so I added it to test. Now, when I compile with
g++ -Wall -o super super.cpp
I get this error output:
super.cpp: In function ‘int main()’:
super.cpp:51:7: error: request for member ‘f’ in ‘sub’, which is of non-class type ‘Sub()’
sub.f();
^
Now I'm even more confused. Sub is clearly a class type. What have I missed?

When the super class constructor is running it only sees the part of the object that is the super class. So when the constructor of Super runs, it sees the object as an object of type Super so it will call Super::f.
As for your error, Sub sub(); declares a function sub which returns an object of type Sub. What you want is to create an object sub. To do this you can declare it like this Sub sub; or, if you are using C++11, like this: Sub sub{};. The same applies for Super super();.

Related

Why does an instance of a derived class call a method from the base class?

Please look at example 1 and example 2.
Example 1 differs from Example 2 only in the overridden method run() from ** class IA **
Question is written at the end.
Example 1:
#include <iostream>
class IA {
public:
void run() {
print();
}
void print() {
std::cout << "IA::print() \n";
}
};
class A : public IA {
public:
void print() {
std::cout << "A:: \n";
}
};
int main() {
A a1;
a1.run();
A * ptr = new A;
ptr->run();
}
This code prints:
IA::print()
IA::print()
Example 2:
#include <iostream>
class IA {
public:
void run() {
print();
}
void print() {
std::cout << "IA::print() \n";
}
};
class A : public IA {
public:
void run() {
print();
}
void print() {
std::cout << "A:: \n";
}
};
int main() {
A a1;
a1.run();
A * ptr = new A;
ptr->run();
}
This code prints:
A::
A::
Why does it print like that? What is the difference?
Thanks.
You chose not to make print virtual. That means no dynamic dispatch occurs. At any point you call the method, the local type information is used to determine which one you call.
void run() {
print();
}
so when you call a non-virtual print, whatever local print function that is seen from where run is written is called.
In IA::run, the only visible print is the IA::print. So IA::run calls IA::print.
In A::run you can see both IA::print and A::print; but the second hides the first. So A::print is called.
What the actual dynamic type of the object is does not matter, because you didn't ask for virtual dispatch. You asked for the function to be picked using local, static type information.
You can ask for virtual dispatch:
class IA {
public:
void run() {
print();
}
virtual void print() {
std::cout << "IA::print() \n";
}
};
I added the keyword virtual to print. And now the first version will call A:: version of print.
Some languages make all methods implicitly virtual. C++ does not, because there is some runtime overhead to virtual methods, and C++ tries not to make you pay for things you aren't using.
In the first program the member function run is a function of the base class. Within the function the static type of the pointe this is IA. The function print is searched in the class IA according to the static type of this.
In the second program the class A has the both functions run and print. They hide the corresponding functions of the class IA. So they are called
From the C++ Standard (13.2 Member name lookup)
1 Member name lookup determines the meaning of a name (id-expression)
in a class scope (6.3.7). Name lookup can result in an ambiguity, in
which case the program is ill-formed. For an id-expression, name
lookup begins in the class scope of this; for a qualified-id, name
lookup begins in the scope of the nested-name-specifier. Name lookup
takes place before access control (6.4, Clause 14).

How to pass an implemented virtual member function as a parameter

#include <iostream>
class virtualClass{
public:
virtual int a() = 0;
};
class UnknownImplementation : public virtualClass{
public:
int a() override { return 1;}
};
class myFramework {
public:
int c(int (virtualClass::*implementedFunc)(void)){
implementedFunc();
return 2;
}
};
int main(){
//some user implements the virtual class and calls myFramework function
myFramework* mfp = new myFramework();
std::cout << mfp->c(&(UnknownImplementation::a)) << std::endl;
}
Hi, I am working on a framework that is supposed call an implemented virtual function and use it. It is similar to the code above.
The compiling errors I get are:
testVirtual.cpp: In member function ‘int myFramework::c(int (virtualClass::)())’: testVirtual.cpp:16:19: error: must use ‘.’ or
‘->’ to call pointer-to-member function in ‘implementedFunc (...)’,
e.g. ‘(... -> implementedFunc) (...)’ implementedFunc();
^ testVirtual.cpp: In function ‘int main()’: testVirtual.cpp:24:47: error: invalid use of non-static member
function ‘virtual int UnknownImplementation::a()’ std::cout <<
mfp->c(&(UnknownImplementation::a)) << std::endl;
How do I fix these problems?
Thanks in advance!
passing an instance of the implemented class and calling the function worked.
To build on sameerkn's comment, this code should be:
#include <iostream>
class virtualClass{
public:
virtual int a() = 0;
};
class mySubclass : public virtualClass{
public:
int a() override { return 1;}
};
int main(){
mySubclass * x= new mySubclass ();
// ...
std::cout << x->a () << std::endl;
}
The point here is that you can pass objects (or pointers) of type virtualClass around - even though they might actually be mySubclass objects in real life - and still wind up in the right implementation of a(). myFramework is entirely unnecessary.
That's what virtual methods are for - consumers of virtualClass don't need to know anything about classes that might - now or in the future - be derived from it, and if I have read your question correctly, this is what you want.

Why can I call instance functions statically?

I was looking around the Notepad++ source code on GitHub recently, and came across a method call like this:
Window::init(hInst, parent);
I searched for the function it was referencing to, and came across a Window class- but the init function was marked virtual, so clearly it was non-static. Thinking I made a mistake, I checked the entire header to make sure there was no static overload of init, and I made sure there was no Window.cpp file. There isn't.
After poking around the source for 15 more minutes, I gave in and git cloned the repo locally so I could open it in Visual Studio. The first thing I did was to build just to make sure this wasn't an accidental merge on behalf of the project developers- the build succeeded.
The next steps I took:
I opened the the file calling Window::init and clicked Go To Declaration on Window. It takes me to the Window class.
I clicked Go To Declaration on the init function. It points me to the signature of the virtual method.
I copy and paste the Window.h file into an entirely new header and replace all references of Window with Foo. When I type in Foo::init, the compiler complains that 'a nonstatic member reference must be relative to a specific object'.
TL;DR: Somehow, the Notepad++ source code calls a non-static method statically, and this builds. Doesn't work with any other class. Proof here and here.
I have spent 2 hours staring at this, but I still don't see how it's possible. Am I missing something?
No, it's not calling a static function. It's just calling the base class's version of init(). Basically, in tClassName::f, you are asking "I want to call that specific version of the virtual function f() in class tClassName".
Generally, it's pretty common to call the base class's counterpart of a virtual function in the derived class. E.g., the factory method pattern:
#include "tObject.h"
#include "tObject1.h" // public inheritance from tObject
#include "tObject2.h" // public inheritance from tObject
#include "tObject3.h" // public inheritance from tObject
class BaseFactory
{
public:
// factory method
virtual tNode *createObject(int id)
{
if (id == 1) return new tObject1;
else return new tObject2;
}
};
class DerivedFactory: public BaseFactory
{
public:
virtual tNode *createObject(int id)
{
// Overrides the default behavior only for one type
if (id == 1) return new tObject3;
// Call the default factory method for all other types
else return BaseFactory::createObject(id);
}
};
Am I missing something?
Yes - context. Notepad_plus_Window derives from Window, and the call to Window::init() is inside of the Notepad_plus_Window::init() method:
class Notepad_plus_Window : public Window {
public:
...
void init(HINSTANCE, HWND, const TCHAR *cmdLine, CmdLineParams *cmdLineParams);
...
};
void Notepad_plus_Window::init(HINSTANCE hInst, HWND parent, const TCHAR *cmdLine, CmdLineParams *cmdLineParams)
{
...
Window::init(hInst, parent);
...
}
In this context, Notepad_plus_Window is calling the base class Window version of init().
Maybe this will confuse you less. You're missing context, at no real fault of your own.
You're not seeing the implicit this in the call.
Take the following example:
#include <cstdio>
#include <iostream>
class Foo {
public:
virtual void bar() {
std::cout << "Foo" << std::endl;
}
};
class Bar : public Foo {
public:
virtual void bar() {
std::cout << "Bar" << std::endl;
}
};
int main() {
Bar bar;
bar.bar(); //-> bar
bar.Foo::bar(); //-> foo
Bar *barp = &bar;
barp->bar(); //-> bar
barp->Foo::bar(); //-> foo
return 0;
}
In the above, we can specify the object on which to call a specific method in the class' hierarchy.
It's not a static function. It's calling a function with a specified (class) scope.
By default, init() will match functions within current class scope, if they do exist. that is an implicit this call, equals this->init(),
But with a specified class/namespace prefix, you can explicit call any particular function without dynamic binding. i.e. ::init() will call the init() function within global scope.
the following code may give you a better understanding
#include <iostream>
class A
{
public:
virtual void test()
{
std::cout << "A" << std::endl;
}
};
class B : public A
{
public:
virtual void test()
{
std::cout << "B" << std::endl;
}
};
int main()
{
A* a = new B();
a->A::test();
return 0;
}

How can an object type be unknown at compile time?

I am currently learning about dynamic binding and virtual functions. This is from Accelerated C++, chapter 13:
[...] We want to make that decision at run time. That is, we want the
system to run the right function based on the actual type of the
objects passed to the function, which is known only at run time.
I don't understand the very idea that the type of an object can be unknown at compile time. Isn't it obvious from the source code?
Not at all. Consider this example:
struct A {
virtual void f() = 0;
};
struct B : A {
virtual void f() { std::cerr << "In B::f()\n"; }
};
struct C : A {
virtual void f() { std::cerr << "In C::f()\n"; }
};
static void f(A &a)
{
a.f(); // How do we know which function to call at compile time?
}
int main(int,char**)
{
B b;
C c;
f(b);
f(c);
}
When the global function f is compiled, there is no way to know which function it should call. In fact, it will need to call different functions each time. The first time it is called with f(b), it will need to call B::f(), and the second time it is called with f(c) it will need to call C::f().
C++ has a concept of pointers, where the variable holds only a "handle" to an actual object. The type of the actual object is not known at compile-time, only at runtime. Example:
#include <iostream>
#include <memory>
class Greeter {
public:
virtual void greet() = 0;
};
class HelloWorld : public Greeter {
public:
void greet() {std::cout << "Hello, world!\n";}
};
class GoodbyeWorld : public Greeter {
public:
void greet() {std::cout << "Goodbye, world!\n";}
};
int main() {
std::unique_ptr<Greeter> greeter(new HelloWorld);
greeter->greet(); // prints "Hello, world!"
greeter.reset(new GoodbyeWorld);
greeter->greet(); // prints "Goodbye, world!"
}
See also: Vaughn Cato's answer, which uses references (which is another way to hold a handle to an object).
Say you have a pointer to base class pointing to a derived object
Base *pBase = new Derived;
// During compilation time, compiler looks for the method CallMe() in base class
// if defined in class Base, compiler is happy, no error
// But when you run it, the method call gets dynamically mapped to Derived::CallMe()
// ** provided CallMe() is virtual method in Base and derived class overrides it.
pBase->CallMe(); // the actual object type is known only during run-time.

calling member function without object error: C++ / (G++) oop

i was curious to know why the following throws an error in g++ (cannot call member function without object). I suppose a workaround would be to have the B class variable as static variable in A - but i was curious to find out why, when there is an instance of A's child class C created, this still throws an error - many thanks!
#include <iostream>
#include <cstring>
using namespace std;
class B {
public:
double var;
public:
friend class A;
B() : var(1) { };
void set(double new_rate);
};
class A {
protected:
B main_B;
public:
virtual void set_rate(double new_rate) { cout << "test";
//B.set(new_rate);
}
};
class C : public A {
};
/*
void B::set(double new_rate) {
var = new_rate;
cout << "worked " <<current_rate <<endl;
}
*/
int main() {
C test_C;
A::set_rate ( 2.00 );
return 0;
}
Firstly,
C test_c();
does not create an instance of C, it declares a function that returns a C. You mean:
C test_c;
Secondly, non-static member functions can only be called on a specific instance of a class. So with the corrected code, you could say:
test_c.set_rate( 2.0);
You can use an explicit <class>:: to call a non-static member function, thereby disabling any virtual function mechanism, but for a non-static member you still need to specify a class instance on which to call the function.
e.g.
int main()
{
C test_C;
test_C.A::set_rate(2.00);
return 0;
}