I don't know how to summarize my question so couldn't find an answer on Google.
When overriding a parent method,
void Child::method(){
//stuff
Parent::method();
}
Works perfectly. But the parent method requires the information from the Child class instance to work properly, which is not given as arguments. So my question is, does C++ have a mechanism to let the Parent know which instance of a Child class calls a Parent method, like without doing Parent::method(this) ?
The thing that makes me think this is, if you do something like this,
int main(){
SomeParentClass::someMethod();
}
It gives: error: call to non-static member function without an object argument. So the compiler needs to know the instance, which was not also given in the child class. But did not raise an error so it must have known the instance.
Edit: I added the Qt tag because I am experimenting on a Qt class. So that I can give an example if needed.
Edit2:
devicedialog.h
class DeviceDialog : public QDialog
{
Q_OBJECT
public:
explicit DeviceDialog(QWidget *parent = nullptr);
int exec() override;
~DeviceDialog() override;
}
devicedialog.cpp
int DeviceDialog::exec(){
// My code.
return QDialog::exec();
}
exec() function activates and shows a QDialog on the screen. However, that way it is called, it seems like the parent method has no way of knowing which dialog to show (no parameters passed). The only knowledge could be the identity of the instance calling it. I am just asking if this knowledge transferred to the method in the background.
I think you are just being confused by the language's attempt to make things easier on you. Your example function is equivalent to
void Child::method(){
//stuff
this->Parent::method();
}
Just as you cannot call a (non-static) method in the child class without an object, you cannot call the parent's method without an object. However, the context is the body of such a method. Within the body, the context is assumed to be *this. Just as you can refer to data members without explicitly prefixing "this->", you can call methods without the prefix.
This is nothing special to member functions of a parent class. Calling a function of the child class via explicitly naming the type:
Child::method();
works in exactly the same way in this regard. Used outside of a member functions definition it causes the same error.
The relevant paragraph of the standard is §9.3.1:
When an id-expression that is not part of a class member access syntax
and not used to form a pointer to member is used in a member of class
X in a context where this can be used, if name lookup resolves the
name in the id-expression to a non-static non-type member of some
class C, and if either the id-expression is potentially evaluated or C
is X or a base class of X, the id-expression is transformed into a
class member access expression using (*this) as the postfix-expression
to the left of the . operator.
So, in other words, the call
Parent::method();
inside a member function is transformed into something akin to
(*this).Parent::method();
This is still a c++ specific question. Qt just utilizes it. You need to study objects, inheritance, and virtual methods.
void Child::method() {
Parent::method();
// this->Parent::method();
}
The above works because the child has access to the parents methods (that are not private). Because the method is an override of the parents virtual method, the only way for the compiler to know you want to call the parents method is to call it with scope resolution '::' in the child.
int main() {
SomeParentClass::someMethod();
}
The above does not work because there is no instantiated object. When you call a method, you call it on the object (unless it is a static method). So instead you would do something like:
int main() {
SomeParentClass parent;
parent.someMethod();
ChildClass child;
child.someMethod(); // accesses the childs overridden method and not the parents.
}
Related
I'm dealing with sample code from a camera SDK, and I have issues getting the frame data "outside" the CSampleCaptureEventHandler class.
class DahengCamera : public QObject
{
Q_OBJECT
class CSampleCaptureEventHandler : public ICaptureEventHandler
{
void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
[grab some data ...]
CopyToImage(objImageDataPointer); // illegal call of non-static member function
}
};
public:
DahengCamera();
~DahengCamera();
private:
void CopyToImage(CImageDataPointer pInBuffer); // I want to have my frame datas here
QImage m_data; //and here
};
I'm using a callback register call to make the camera "DoOnImageCaptured" event called once a frame is grabbed by the system. But I'm stuck getting the data outside this method. CopyToImage() is supposed to get a reference to QImage or to write into m_data, but I have "illegal call of non-static member function" errors. Tried to make CopyToImage() static, but it just move the problem...
How can I solve this ?
Thanks !
CopyToImage is a private non-static function in the class DahengCamera.
The fact that CSampleCaptureEventHandler is a nested class inside DahengCamera allows it to access DahengCamera's private members and functions (as if it were decleared a friend class), but this does not provide CSampleCaptureEventHandler with a pointers to any DahengCamera objects.
You need to provide the actual instance of the CSampleCaptureEventHandler object on which DoOnImageCaptured is called with a pointer/refence to the DahengCamera object on which CopyToImage should be called. You might consider providing this pointer/reference to the DoOnImageCaptured object to CSampleCaptureEventHandler's constuctor (i.e. dependency injection).
(And - for your own sake - do not try to "fix" this by turning CopyToImage or m_data into static - this would create only a horrible mess)
Let's say I have a Parent class that implements a virtual method, overridden by a Child class. I understand that if the method is called on a variable of type Parent then the compiler must use some way of checking which implementation of the method should be called at run time, but surely this is not necessary if the variable is of type Child? In this case, assuming that the method is not overridden again by a child of Child, will the compiler devirtualise the method since it is known that the variable will definitely contain a Child, and is this compiler specific?
In order to de-virtualize a call, the compiler would have to know for certain that there are no derived types of Child that it might be passing through the code with:
void f(Child* c) {
Child* l = new Child;
c->virtFn();
l->virtFn();
}
The c call to virtFn could be for a derived type, but the l call can't.
C++11 introduced the final keyword that can assist with this and allow the compiler to devirtualize calls through a terminal class pointer/ref.
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
Consider the following situation - pair of Parent and Child classes. Parent constructor requires a Child class to be instantiated, because it has to initialize it in a special way. Both Parent and Child may be derived, such that DerivedParent uses DerivedChild.
There's a problem, however - because in Parent::ctor call from DerivedParent::ctor, base class should have an instance of DerivedChild instead of Child. But that would require calling a virtual method some way, what is prohibited. I'm talking about something like this:
class Child
{
public:
virtual std::string ToString() { return "Child"; }
};
class DerivedChild : public Child
{
public:
std::string ToString() { return "DerivedChild"; }
};
class Parent
{
protected:
Child * child;
virtual Child * CreateChild() { return new Child(); }
public:
Parent() { child = CreateChild(); }
Child * GetChild() { return child; }
};
class DerivedParent : public Parent
{
protected:
Child * CreateChild() { return new DerivedChild(); }
};
int main(int argc, char * argv[])
{
DerivedParent parent;
printf("%s\n", parent.GetChild()->ToString().c_str());
getchar();
return 0;
}
Let's get a real-world example. Suppose, that I want to write wrapper for WinApi's windows. The base Control class should register class and instantiate a window (eg. RegisterClassEx and CreateWindowEx), to properly set it up (for example register class in such way, that window structure has additional data for class instance; set up generic WndProc for all Controls; put reference to this by SetWindowLongPtr etc.)
On the other hand, derived class should be able to specify styles and extended styles, class name for window etc.
If constructing instance of window in the Control's constructor is a contract to be fulfilled, I see no other solution than to use VMs in ctor (what won't work).
Possible workarounds:
Use static polymorphism (eg. class Derived : public Base), but it will not work, if one wants to derive from Derived;
Pass a lambda from derived to base ctor if it is possible - it will work, but it's a total hardcore solution;
Pass a ton of parameters from derived to base ctor - it shall work, but won't be neither elegant, nor easy to use.
I personally don't like neither of them. Out of curiosity, I checked, how the problem is solved in Delphi's VCL, and you know what, base class calls CreateParams, which is virtual (Delphi allows such calls and guarantees, that they are safe - class fields are initialized to 0 upon creating).
How can one overcome this language restriction?
Edit: In response to answers:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
It will work, but it's not an option - quoting the famous C++ FAQ:
The first variation is simplest initially, though the code that actually wants to create objects requires a tiny bit of programmer self-discipline, which in practice means you're doomed. Seriously, if there are only one or two places that actually create objects of this hierarchy, the programmer self-discipline is quite localized and shouldn't cause problems.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
It's not an option, because it will work only once, for base class and its immediate descendant.
Make the child pointer a constructor argument, for example to a factory function.
This is, so far, the best solution - injecting code into base ctor. In my case, I won't even need to do it, because I can just parametrize base ctor and pass values from the descendant. But it will actually work.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
Yea, but it has some drawbacks:
Someone, who derives from my classes may publish his ctor and bypass the security measures;
It would prevent one from using references, one would have to use smart pointers.
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
No, calling a virtual method in the constructor dispatches to the most-derived complete object, which is the one under construction. It's not prohibited, it's well-defined and it does the only thing that would make sense.
A C++ base class is not allowed to know the identity of the most derived object, for better or worse. Under the model, the derived object doesn't start to exist until after the base constructors have run, so there's nothing to get type information about.
Some alternatives in your case are:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
Make the child pointer a constructor argument, for example to a factory function.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
class Parent {
public:
void func1(); // Complete meaningful definition in parent given.
virtual HRESULT func2()=0; // Bcoz of this function Parent class is abstract.
};
class Child: public Parent {
public:
void func1(); // Different definition in child.
};
Is this possible in C++ ? I am overriding func1() which is NOT virtual and it already has a definition in parent abstract class.
[assuming here Child extends Parent, unlike what the code snap shows]
Yes it is possible [it is called hiding] - but you will not get a dynamic dispatch behavior.
The static type will define which method will be invoked, and not the dynamic type.
For example:
Parent* p = new Child;
p->func1();
Will invoke Parent::func1()
while:
Child* c = new Child;
c->func1();
Will invoke Child::func1()
No, it's not possible to actually override the definition in the parent (at least when talking about C++, "override" is normally reserved specifically to referring to virtual functions). Instead, defining a function with the same name in the child class simply hides the function in the parent that has the same name (i.e., in the context of a child object, looking for that name will only find the function in the child, not the one in the parent).
If you want to (and the functions have different signatures) you can also get the functions in both the parent and the child treated as overloaded, so a call will try to call whichever matches better:
struct parent {
void func1(char) {}
};
struct child : public parent {
void func1(long) { }
using parent::func1;
};
Now, you get:
child c;
c.func1('a'); // calls parent::func1
c.func1(123L); // calls child::func1
This is yet a third type of behavior though, different from having a virtual function or having a function in the child that hides the one in the parent.
With a virtual function, the selection of which function is called is based on the dynamic type, so if you have a pointer/reference to the base class, the function called depends on whether that refers to an object of the base or derived class.
When you hide the function, the function that's called is based on the static type, so if you call it via a pointer/reference to the base, it calls the base function, even if that actually refers to an object of the derived class. If, however, you use a pointer or reference to (or directly use an instance of) the derived class, it'll invoke the function in the derived class.
With the using statement, you get function overloading, so when you call the function (in the context of the derived class) the function that's called is based on which function's signature is the best match for the parameter(s) you pass.
You can overload it, if they have distinct argument types.
You can hide it, in the sense shown here, so that Child::func1 will be called instead of Parent::func1 in code that knows it's looking at a child instance. However, as amit points out, you don't get dynamic dispatch.
struct StaticParent {
void foo();
};
struct StaticChild : public StaticParent {
void foo();
}
StaticChild sc;
sc.foo(); // calls StaticChild::foo
StaticParent &sp = sc;
sp.foo(); // calls StaticParent::foo
struct VirtualParent {
virtual void foo();
};
struct VirtualChild : public VirtualParent {
virtual void foo();
}
VirtualChild vc;
vc.foo(); // calls VirtualChild::foo
VirtualParent &vp = vc;
vp.foo(); // calls VirtualChild::foo
Yes, this is valid C++ syntax and will define a Child::func1 which hides Parent::func1 in Child.
However, this does not mean that it fully replaces Child::Parent::func1. This function can still be called explicitly on an element of child.
Child c;
c.Parent::func1();
Also, this function will not be virtual. Thus, the following..
Child c;
Parent& p = c;
p.func1();
will call Parent::func1 and not Child::func1.
Most has been said.
Your expectations would be right if you talk about java. In java any non-private, non-final method could be overridden. Maybe you are more familiar with an other programming language than C++
By the way, two things are wrong in your code
"class" must be written lower case
the default access of members in class is "private". It is NOT allowed nor useful to override private members which are non-pure
I know this question has a similar title to this: C++: calling member functions within constructor? but I am asking a more general question.
Is it good practice to call member functions from within a constructor? It makes reading the code easier and I prefer the encapsulation type way of doing it (ie. each block of code has a single objective).
An illustrative example, in python:
class TestClass:
def __init__(self):
self.validate()
def validate(self):
# this validates some data stored in the class
Is this a better way of doing it than writing the validate code inside the constructor? Are there drawbacks to this method? For example is it more costly with the function overhead?
I personally prefer it for readability but that's just my preference.
Cheers
I don't think there is anything inherently wrong in calling member functions from a constructor provided that they are not virtual functions.
The problem with calling virtual member functions from a constructor is that a subclass can override the function. This will cause the constructor to call the overridden implementation in the subclass, before the constructor for the subclass part of the object has been called.
In Java, any one of the private, static or final access modifiers will make the method safe to call from a constructor by preventing a virtual call to the superclass method. I don't think these techniques are available in Python.
There is at least one associated "gotcha" you should be aware of:
N3797 12.6.2/14
Member functions (including virtual member functions, 10.3) can be called for an object under construction. Similarly, an object under construction can be the operand of the typeid operator (5.2.8) or of a dynamic_cast (5.2.7). However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result
of the operation is undefined. [Example:
class A {
public:
A(int);
};
class B : public A {
int j;
public:
int f();
B() : A(f()), // undefined: calls member function
// but base A not yet initialized
j(f()) { } // well-defined: bases are all initialized
};
class C {
public:
C(int);
};
class D : public B, C {
int i;
public:
D() : C(f()), // undefined: calls member function
// but base C not yet initialized
i(f()) { } // well-defined: bases are all initialized
};
— end example]
The main problem with this is that the member function has to work with an object that may be only partially initialized. And if it (even accidentally) passes a reference to the object somewhere else, other code has to od the same. This can get pretty confusing and error-prone, especially once you start overriding such a function in a subclass.
So in general, this practice should be avoided or at least confined to functions that can't be overriden, and they should never pass a reference to the object being constructed to any other code.
I'm more familiar with C++ than Python, but I see no problem with calling member functions from constructors, especially when this practice is able to factor out similar code from multiple constructors. Anything that reduces redundancy is good in my books.
From a readability point of view it is definitely better. One thing you might have to ask yourself here though is whether the validate method is allowed to run after the object is initialized. If that is not the case, you can a) use some kind of private initialized variable or b) use the Builder pattern to get your objects into a valid state before using them.
Make sure the function is private. You do not want to mess with subclasses overriding it (Unless this is desired by design, in which case make it abstract/virtual).
first, this member function cannnot be virtural function,
second, this member function must be implemented in the same file, if you declare it in *.h, then implement it in *.cpp, gcc/clang will report this error undefined reference to