This question already has answers here:
virtual function default arguments behaviour
(7 answers)
Closed 9 years ago.
the below is my test code, i think it will output "Der:12", but the result is "Der:11", any one can tell me why output this, and where is the default argument store?
#include <stdio.h>
class Base{
public:
virtual void show(int i = 11)
{
printf("Base:%d\n", i);
}
};
class Der : public Base{
public:
virtual void show(int i = 12)
{
printf("Der:%d\n", i);
}
};
int main()
{
Base *p = new Der();
p->show();
return 0;
}
Hmmm, I'm not sure it's actually valid to override a virtual function with a different default parameter, and it's certainly not sensible. But on the other hand, the compiler is doing the right thing, even if it's contrary to your expectations.
Base *p;
p->show();
What happens here is that the compiler looks into Base for a function taking no arguments. There isn't one, but it finds the one-argument function and calls show(int) with the default parameter of 11.
But the function is virtual, and so because p's dynamic type is Der, it's Der::show(int) that actually gets called -- but crucially, still with Base's default argument of 11, but the default argument is looked up statically, not using run-time dispatch.
I haven't tried it, but I'd imagine if you said
Der *p = new Der();
p->show();
you'd get 12 output instead.
Related
This question already has answers here:
Calling virtual functions inside constructors
(15 answers)
Closed 1 year ago.
class A{
virtual void setEnable(bool enable) = 0;
};
class B : A{
B() {
setEnable(true);
}
~B() {
setEnable(false);
}
bool enable_ = false;
void setEnable(bool enable) override {
enable_ = enable;
}
};
Am I correct in understanding that the B :: setEnable function will be added to the vtable only after the constructor exits and this is undefined behavior?
Am I correct in understanding that the B::setEnable function will be added to the vtable only after the constructor exits and this is undefined behavior?
No. Inside the body of the A constructor, the A object is fully initialized, but the B object is not. The problem with calling a virtual function from a constructor is that it will unintuitively call the method of the same type that the constructor belongs to, without the polymorphic behavior.
This question already has answers here:
call to pure virtual function from base class constructor
(8 answers)
Calling virtual functions inside constructors
(15 answers)
Closed 1 year ago.
I am trying to call an overriden function from the parent, and found out that it just crashes.
This is quite hard to describe, so here the minimal reproducible code:
#include <iostream>
class A
{
public:
A()
{
init1();
}
void init1()
{
printf("1");
init2();
printf("2");
}
virtual void init2() = 0;
};
class B : public A
{
public:
B()
: A()
{}
void init2() override
{
printf("hello");
}
};
int main()
{
B b;
return 0;
}
On MSVC 2019 it crashes, on http://cpp.sh/ it outputs "1" and then main() returns 0, but we never see "hello" or "2".
Why does it crash? What happens from a low level point of view? Is A trying to call its own init2()?
Is there a way of doing it, so I don't have to, in every derived class, add init2() in its constructor?
You can't call a derived class's overriden methods from within a base class constructor (or destructor). The derived class portion of the object doesn't exist yet.
So, to answer your questions:
yes A::A() is trying to call A::init2(), not B::init2(), and thus crashes from calling a pure virtual method.
There are ways (like via CRTP) for a base class constructor to call a derived class method, but doing so has limitations to it (ie, not being able to access any derived class data members since they still don't exist yet, only base class data members can be accessed). In your example, B::init2() doesn't access anyB data members, so it is possible for A::A() to call B::init2(), but in general you really need to wait for B to begin/finish constructing itself before you can safely call B::init2().
This question already has answers here:
Function with same name but different signature in derived class not found
(2 answers)
Closed 2 years ago.
I am passing different types of argument to the fun(), the code gets compiled, but still, the same function that prints "Class B" is getting executed. Shouldn't there happen overloading of functions?
Why does this happen?
#include <iostream>
using namespace std;
class A
{
public:
void fun(int x)
{
cout<<"class A"<<endl;
}
};
class B: public A
{
public:
void fun (char c)
{
cout<<"Class B"<<endl;
}
};
int main()
{
B obj;
obj.fun('c');
obj.fun(3);
}
B::fun() shadows A::fun() and an int literal is easily converted to char so your compiler had no difficulty with resolving that call. You can add using A::fun; to B's definition to make it visible.
When writing obj.fun(<argument>), first what fun to be called will be looked up. Since the compiler only looks at B first, it finds B::fun(char) both times, which is what is selected.
It would only look at A if there was no one parameter member function, so fun in B effectively hides fun in A. To overcome that, you can directly call A's fun like:
obj.A::fun('c'); // A
static_cast<A&>(obj).fun('c'); // A
Or you can bring A::fun(int) into B by using it:
class B: public A
{
public:
using A::fun;
void fun(char c)
{
std::cout << "Class B\n";
}
};
obj.fun('c'); // B
obj.fun(3); // A
You cannot overload like this across a heirarchy.
Name lookup happens before overload resolution and access control.
Once a function name is found in B, other classes up the heirarchy will not be checked. So all the candidate functions for a particular function call would be the functions present in B.
You will have to make the function name in A visible in B by saying:
using A::foo;
inside class B.
Now the overload will work as you expect.
This question already has answers here:
Function pointer to member function
(8 answers)
Closed 4 years ago.
class Person;
class Command {
private:
Person * object;
//what is this? - a functor?...
void (Person::*method)();
public:
Command(Person *a, void(Person::*m() = 0): object(a),method(m) {}
void execute() { (object->*method(); }
};
// defining class Person here
class Person {
private:
string name;
Command cmd;
public:
Person(string a, Command c): name(a),cmd(c) {}
void talk();
void listen();
};
I was wondering what line 6 here means? Is that a way of defining a function or a functor? Also where does this type of function def appear and tends to be used? I found this example Under "Design Patterns" within Object Oriented Programming - this approach type is called Behavioural Command Pattern.
This is a pointer to Person class member taking no parameters and returning void.
Such initialization allows class Command referring to custom methods of class Person. Imagine class Person to be defined like this:
class Person
{
public:
void f1() { std::cout << "Call f1\n"; }
void f2() { std::cout << "Call f2\n"; }
};
Then we can create Command objects in this way:
Person p;
Command c1(&p, &Person::f1);
Command c2(&p, &Person::f2);
Executing these commands calls corresponding methods of given person:
c1.execute(); // prints "Call f1"
c2.execute(); // prints "Call f2"
This code line void (Person::*method)(); is a function pointer. void means that the function that is pointed won't return any data. (Person::*method)() is the definition of the pointer, the pointer will point to a void function.
In this page you can see how the syntax is:
Function Pointer Syntax
The syntax for declaring a function pointer
might seem messy at first, but in most cases it's really quite
straight-forward once you understand what's going on. Let's look at a
simple example:
void (*foo)(int);
In this example, foo is a pointer to a function taking one argument,
an integer, and that returns void. It's as if you're declaring a
function called "*foo", which takes an int and returns void; now, if
*foo is a function, then foo must be a pointer to a function. (Similarly, a declaration like int *x can be read as *x is an int, so
x must be a pointer to an int.)
The key to writing the declaration for a function pointer is that
you're just writing out the declaration of a function but with
(*func_name) where you'd normally just put func_name.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
c++ virtual function return type
I have a simple but confusing question here. Is it legal to have a different return value type for overridden methods than the abstact ones defined in the base class?? I did that and the compiler didn't complain... could someone please explain?
class MyBaseClass
{
int value;
public:
virtual int getValue() = 0;
};
class MyClass : public MyBaseClass
{
double value;
public:
virtual double getValue(); // here!!! return is double, not int
};
double MyClass::getValue()
{
return this->value;
}
The compiler totally accepted something similar (MSVC und MinGW)... could anyone please exaplain to what extent this is legal?
The return type is allowed to differ but only in a bery restrictive way and you code is illegal. The only way the return type of an override is allowed to differ is that can be covariant if yhe return type of the base is a pointer or a reference. Put differently: if the base returns a pointer or a reference to a base class the overrude is allowed to return a pointer or a reference, respectively, to a class derived of the base.
Are you overriding ? it looks like you have written a method and nothing else.