Is the this pointer ever required? I guess you'd need it if you were functionally passing around the instance of the class pointed to by this. But in terms of setting/retrieving/calling/whatever members, is this always optional?
I've tagged this C++ because that's the language I'm specifically wondering about, but if someone can confirm that the construct is the same for Java and other OO languages that use a this pointer, it'd be appreciated.
There's three cases I can think of:
When you simply want to pass a pointer to the current class:
class B;
struct A {
B* parent_;
A(B* parent) : parent_(parent) {}
};
struct B {
A* a;
B() : a(new A(this)) {}
};
In a constructor or member function, where a member is shadowed by an argument:
struct A {
int a;
void set_a(int a) { this->a = a; }
};
Here, the member variable "a" is shadowed by the argument "a", so this-> is used to access the member instead of the argument.
(example above edited to be a function rather than constructor, since you wouldn't normally assign this way in a constructor)
When accessing a public/protected member variable or function in a base class of a template class
template <class T>
struct A {
int a;
};
template <class T>
struct B : public A<T> {
int f() { return this->a; }
}
here, a alone would not be a dependent name, so the compiler would expect to find a declaration of it in B or a base of B that does not depend on T. Adding this-> makes the lookup dependent on the type of this, and since this is a dependent type, the lookup of a is deferred until f() is instantiated.
One could write return A::a instead of return this->a, but in the presence of multiple bases, whether direct or indirect, using this-> is more flexible. This alternative syntax is also limited to member variables and non-virtual functions - if it is used with a virtual function, it the function will be called directly instead of doing virtual function call.
You need it when you have a local variable that has the exact same name as the member variable. In this case, the local variable is said to shadow the member variable. To get to the member variable in this situation, you must use this.
Some people consider it good practice to explicitly mention that the variable you are modifying is a member variable by using this all the time, but this is not always the case.
sometimes "this" is required, maybe when you are passing your object to another function.
look at this c# code( for opening a modal form with this parent)
Form1 f = new Form();
f.ShowDialog(this);
Related
Disclaimer: I am a C developer and it's my first time that I'm trying something like this in C++. I have zero experience with the language.
I have a class Bob that has a pointer to a function myFunction as a private member.
I want to inherit the class Bob and pass a method of the derived class to the pointer function using the base class constructor.
This is my code:
#include <iostream>
using FuncHandler = void (*)(int x);
class Bob
{
protected:
Bob(FuncHandler x)
{
myFunction = x;
// When I call the function here
// I get garbage...
// x value is = 932452288
myFunction(10);
}
private:
FuncHandler myFunction;
};
class Alice : public Bob
{
public:
Alice() : Bob(reinterpret_cast<FuncHandler>(&Alice::foo))
{
}
void foo(int x);
};
void Alice::foo(int x)
{
std::cout << "x value is = " << x << "\n";
}
int main(void)
{
Alice obj1;
return 0;
}
The question is what did I do wrong that I'm getting garbage to the output?
The using FuncHandler = void (*)(int x); is a convenient name for a function pointer.
Alice's void foo(int x); is not a function, it's a member function. A member function is a different kind of thing than a freestanding function.
Fortunately, in this particular case, the code does not need to access the function as Alice's member function, it can use a static class function, which is compatible with a function pointer. Assuming the signatures match, which in this case they do.
Change void foo(int x); to static void foo(int x);.
Then change Alice() : Bob(reinterpret_cast<FuncHandler>(&Alice::foo)) to Alice() : Bob(&Alice::foo) and the code is all set.
CAUTION: if the foo function needed to access Alice's instance state, it would have problems because at that construction point in the code the Alice object has not been constructed yet.
I see two major issues with your approach.
First, base classes are constructed before derived classes. Inside the base class constructor, the derived class does not yet exist, so calling a non-static member function of the derived class is undefined behavior.
Second, your functional cast is invalid. It works in one sense, but the converted value cannot be used safely. Whenever you feel the need to use reinterpret_cast, don't; use static_cast or dynamic_cast instead. While there are some valid uses for reinterpret_cast, beginners tend to use it in bad locations. The static and dynamic casts are powerful enough for most needs and weak enough to fail when you try to do something inappropriate, such as your conversion. (Pointer-to-member-function is a different beast than pointer-to-function. While the compiler might allow converting one to the other, it is not safe to invoke the function through the converted value.)
You possibly should go back to the drawing board. At the very least, remember to mark member functions static if they do not use the this pointer. You might be letting your C background cloud your C++ thinking. (Of course, that is guesswork since I do not know your real problem.)
In a larger code base I have encountered code like this (see on godbolt):
struct Foo {};
struct Base {
Foo* a;
};
struct Bar : public Base {
static Foo* Bar::*mybar[];
};
Foo* Bar::Bar::*mybar[] = {
&Base::a
};
To be honest, I'm baffled. This looks like it's initializing a static array of Foo pointers in Bar with a non-static member variable of Base. How is that even possible without an object?
(Disclaimer: This is found in production code that actually works - hopefully not relying on UB?)
Also, is there any problem if I remove the qualified name lookup like here? I'd like to refactor the code and make it more readable. All these Bar::s seem quite superfluous, but since I'm not feeling so comfortable with the code I'd rather understand the implications first.
Unlike normal pointers, class member pointers can be though of as an offset into the class, where they are telling you which member of an object they point to. So in your code, mybar is an array of class member pointers. When you do
Foo *Bar::Bar::*mybar[] = {
&Base::a
};
you initialize the array with a pointer to the a member of Base. This isn't actually pointing to an a, it just tells the compiler which member of the object to return if you access it with an object. That would look like
Base foo; // now we have an actual object
foo.*mybar[0]; // access the `a` member of `foo` by using the "offset"
How is that even possible without an object?
It is possible to create pointer to member variables without an object. The pointers can be used to dereference an actual member only in the presence of an object.
Simpler example:
struct Foo { int m; int n};
using MemberPtr = int Foo::*;
MemberPtr p1 = &Foo::m; // Instance of Foo is not needed.
MemberPtr p2 = &Foo::n; // Instance of Foo is not needed.
*p1 = 10; // Not allowed.
*p2 = 20; // Not allowed.
Foo a;
a.*p1 = 10; // Changes a.m
a.*p2 = 20; // Changes a.n
Foo b;
b.*p1 = 30; // Changes b.m
b.*p2 = 40; // Changes b.n
Please note that you are able to change values of members of two instances of the class using the same pointer to member variables.
To start with, Bar::mybar is an array of pointers to members. Those aren't actual pointers. They are more like an abstraction over an offset into the object. They allow accessing members indirectly. Given a Base object (or one derived from it), we can invoke them, as follows
aBar.*mybar[0] // This resolve to a Foo* inside aBar
The other thing of note, is that in your example the object in namespace scope is not the definition of Bar::mybar. It's an unrelated array. The correct definition would be
Foo* Bar::* Bar::mybar[] = {
&Base::a
};
It is because your definition was wrong that removing some of the qualified name had no effect. When you removed it, you were left with
static Foo *mybar[];
Foo Bar::*mybar[] = {
&Base::a
};
The types of the declaration and "definition" mismatch. But you got no error because those are in fact different objects.
In the correct definition, every Bar:: qualifier is required and serves a different purpose. One serves to create the correct type (pointer to member of Bar), the other designates the static member of Bar that is being defined, and is required in every static class member definition.
Is it legal in func1 and func2? Class methd contains the same class object.
example:
class Foo
{
public:
void func1() {
//...
Foo foo; // Is it legal?
//...
}
// Is it legal in paramete?
void func2(Foo object) {
//...
}
// It is legal using reference
// http://stackoverflow.com/questions/6921185/why-do-objects-of-the-same-class-have-access-to-each-others-private-data
void func3(Foo& object) {
//
}
};
Is it legal?
yes
Why?
class Foo
{
public:
void func1() {
//...
Foo foo; // Is it legal?
//...
}
};
The body of a class member function is compiled after the entire class definition has been considered.
For this reason, the entire class is available to the method's implementation, including methods and members declared after the current method.
This is covered in [class.mem]
Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes).
Yes, it is legal in all of your cases.
But it is illegal in constructor of copy:
// here should be 'const Foo&'
Foo(const Foo object);
Sloppy speaking, the only difference between a free function and a member function is that a member function get a this passed as first argument (you dont see it explicitly but it is there). This is not completely true, but true enough to understand that there is no reason not to have a Foo inside a member function of Foo.
What you cannot do is something like this:
struct Bar {
Bar x;
};
thats not only a quite strange construct ("its turtles all the way down", just in case you know that quote) but also your complier will clearly tell you that it cannot work.
Yes, it is legal in all of those three cases.
of course it is 100% legal, that is what many operators need as parameter, and many other functions use...
look this example taken from the String class:
string& operator+= (const string& str);
so string class has a function taking another string as parameter...
Trying to design some exception-free classes, I have an inheritance structure similar to this, but I have found the noexcept specifier to be of little to no help when working with member functions as the specifier is not scoped as being within the function.
class Base
{
protected:
Base() noexcept {}
};
class Derived : public Base
{
public:
// error: 'Base::Base()' is protected
Derived() noexcept(noexcept(Base{})) : Base{} {}
// error: 'foo' was not declared in this scope
Derived(int) noexcept(noexcept(foo())) {}
// error: invalid use of 'this' at top level
Derived(float) noexcept(noexcept(this->foo())) {}
void foo() noexcept {}
};
Demo
Is this perhaps something that is being improved in C++17? Trying to search for this has yielded no relevant results. For now I've resigned to some very ugly (and possibly incorrect) attempts such as noexcept(noexcept(static_cast<Derived*>(nullptr)->foo())), but this doesn't assist in the case of the base class constructor, which is protected.
Is it even currently possible to declare a noexcept specifier which references a protected base class method like this? noexcept(auto) might be relevant, but of course isn't possible yet. Have I overlooked anything else that would allow me to include this specifier, or do I simply have to omit it in that case?
You can work around it by using an expression where the Base constructor is in scope like this:
struct test_base : public Base {};
Derived() noexcept(noexcept(test_base())) : Base() {}
I believe the reason you cannot use Base() directly is related to this question.
The way protected access specifier works, it allows the derived class
B to access the contents of an object of base class A only when that
object of class A is a subobject of class B. That means that the only
thing you can do in your code is to access the contents of A through
B: you can access the members of A through a pointer of type B * (or a
reference of type B &). But you cannot access the same members through
a pointer of type A * (or reference A &).
It's the same as if you had a member function like this:
void badfunc()
{
B b;
}
You're trying to use Base's constructor directly instead of going through Derived. When you initialize the base in the constructor initialization list, that is a special context that allows you to call the constructor because you're doing it as part of initializing Derived.
This is really multiple questions in one.
About this...
From my understanding, the use of this is supposed to be completely superfluous but compiler support for C++11 is not entirely universal. This should work, according to the C++11 standard:
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(Base::func())) {}
};
Note that base_func() is a non-static member function, but because it appears in an "unevaluated operand" it is okay. From n3337 sec 4.1.1:
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
...
if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
However, some compilers do not support this. You are then forced to use std::declval:
#include <utility>
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(std::declval<Base>().func())) {}
};
About accessibility...
I read through the relevant parts of the standard about "unevaluated operands" and "member access control" and I have come to the conclusion that the standard is a bit ambiguous. It mentions that a protected name can be used only by members, friends, and derived classes. The question is whether unevaluated operands "use" the member names which appear in them. They certainly don't odr-use the member names, and can even use member names if no definition is provided, and this kind of ambiguity is exactly why the term "odr-use" even exists! For example,
int f(); // No definition anywhere in program
int x = sizeof(f()); // Completely valid, even without definition of f
struct X {
X() = delete; // Cannot use this constructor
};
int xsize = sizeof(X{}); // Completely valid
Even though it is somewhat unclear, I have a hard time imagining that the C++ committee could have intended to let you use deleted member functions in unevaluated operands but not inaccessible member functions. However, I am not certain.
Note that the above code compiles without error both with GCC and Clang. However, the following code is does not:
class X {
X(){}
};
class Y {
Y() = delete;
};
bool xokay = noexcept(X{}); // Error!
bool yokay = noexcept(Y{}); // Ok
Both GCC and Clang accept Y but not X, which seems a bit weird to say the least. The following code is accepted by Clang but not GCC, and using std::declval does not help:
class Base {
protected:
void func();
};
class Derived : public Base {
// Clang accepts this, GCC does not.
void func2() noexcept(noexcept(Base::func())) {}
};
What a mess.
Conclusions
The conclusion here is that it seems that there is plenty of inconsistency to go around, and plenty of gaps between current compilers and the C++11 specs.
Let's say we have:
class Base {...}
class A : public Base {...}
class B : public Base {...}
Is it possible to set as argument type of a generic method:
myMethod([typei'mlookingfor] c) {}
so that I can pass Base, A and B to myMethod() without overloading the method?
and also make it work with references and pointers?
If a pointer or a reference to the base class works for you, just use that:
void myMethod(Base& c) {}
A a;
B b;
myMethod(a); //OK
myMethod(b); //OK
Note that you'll have to use references or pointers to prevent object slicing. If the method is myMethod(Base c), you'll lose type information of derived objects.
If not, you can use a template
template<typename T>
void myMethod(T& c)
{
}
A a;
B b;
myMethod(a);
myMethod(b);
Q: Is it possible to define the type of a method argument to be a class or any derivate class?
A: Sure. Why not?
If you want a "generic" parameter that can be any arbitrary type, just use a template.
Otherwise, if you want "class or any subclass", just use the base class.
Useful quote:
http://wiki.answers.com/Q/What_are_the_concepts_of_object_oriented_programming
Polymorphism allows the programmer to treat derived class members just
like their parent class' members. More precisely, Polymorphism in
object-oriented programming is the ability of objects belonging to
different data types to respond to method calls of methods of the same
name, each one according to an appropriate type-specific behavior.
Which, I believe, is exactly what you're looking for :)
There are 2 ways how to do this. 1st is dynamic polymorphism. Works only with pointers and refs. There is small run time overhead:
void myMethod(Base& x) { ...}
2nd - static polymofism:
template<class T>
std::enable_if<is_base_of<Base,T>::value>
myMethod(base x) {...}