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...
Related
The code below compiles just fine (unless the call to method is uncommented).
Why is it allowed to "call" to the default constructor? (there shouldn't be one)
Why is the declaration of the member function not an error?
.
extern "C"
{
struct S
{
int some_int;
void method(){}
};
}
int main()
{
S s();
// s.method();
return 0;
}
First, S s(); declares a function named s that takes no arguments and returns an object of type S. Just like int f();.
Second, that extern "C" isn't relevant here. It's used, roughly, for functions that are written in C and called from C++. It doesn't mean "pretend that this code is C code".
Third, S does have a default constructor. The compiler generates one. In this case it doesn't do anything, because there are no members of S that require non-trivial initialization. To use the default constructor you'd write S s; or S s{};.
Fourth, the reason that declaring a member function is okay is that a struct and a class in C++ can have member functions. I know, that sounds tautologous, but it's important to keep in mind that a struct can have member functions, static data, private, protected, and public members just like a class. The only differences between a struct and a class is that by default members of a class are private while members of a struct are public, and by default a base of a class is inherited privately while a base of a struct is inherited publicly.
Adding a default constructor (although it's optional here) and using curly-braces rather than parenthesis or you don't even need to use that, will solve your issue:
....
struct S {
S() {} // declaring the constructor explicitly here
};
....
int main(void) {
S s{}; // Don't use s() - a function, instead, call the
// default constructor
// S s;
s.method();
return 0;
}
Scenario:
I have class like below which hooks up a lambda in the constructor itself. And the lambda calls a class member function in turn.
Code:
class SomeClass {
public:
typedef std::function<void(int)> Callback;
void ListenForCallback(const Callback& callback) {
m_callback = callback;
}
private:
Callback m_callback;
}
class MyClass {
public:
MyClass() {
m_some_class = std::make_unique<SomeClass>();
// Here in constructor itself I pass this pointer and hooking up to a lambda which calls a member function. Is this legal?
m_some_class->ListenForCallback([this](int value) {
std::cout << "Value is: " << value << std::endl;
TakeAction();
})
}
private:
std::unique_ptr<SomeClass> m_some_class;
void TakeAction() {
// Please do something
}
}
Question:
I was skeptical about using the this pointer in the MyClass's constructor itself. And even further skeptical about hooking up a lambda calling a member. But, I found that above code works! Am I doing everything legal and correct in above code?
Is it valid to refer to this pointer in the constructor of a class? I wish to know if its valid/invalid and the explanation or reasoning behind the answer.
Environment:
C++ 14 code compiled with Clang and GCC compilers.
This is fine. The object of the class MyClass exists at this point. So the pointer this is valid, and of course the class someClass has been completely constructed as well.
The only thing to watch out for is the order of member initialisation of MyClass - but only really in the initialiser list, although since you are not using an initialiser list here it is not an issue in this example anyway...
It can appear within the body of any non-static member function.
Source: https://en.cppreference.com/w/cpp/language/this
Constructors are non-static member functions, so it is legal.
I have always been under the impression that C/C++ is parsed in 1 pass, therefore, a symbol must be declared before it can be used.
Thus this does not work:
void a()
{
b();
}
void b()
{
}
unless we forward declare void a();
However, I noticed that this does work:
class Foo
{
public:
void a()
{
b();
}
void b()
{
}
};
Why does this work? If C++ is parsed in a single pass through the code then this should not work I would think because the symbol Foo::b() has not been defined when it is called.
The definition of your class:
class Foo
{
public:
void a() { b(); }
void b() { }
};
has the same meaning than:
class Foo
{
public:
void a();
void b();
};
void Foo::a() { b(); }
void Foo::b() { }
This is why the function body sees all the members, as if the class was already completely defined. This is by the ways stated in the C++ standard:
3.3.7/1 The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies,
brace-or-equal-initializers of non-static data members, and default
arguments in that class (including such things in nested classes).
The compiler still parses the file in a single pass. But the parsing the grammatical construct is only a part of the larger compilation process, in which applying the context to the parsed grammar production plays also a role (see also this SO question).
There are things called forward references (different from forward declaration)
class C
{
public:
void mutator(int x) { myValue = x; }
int accessor() const { return myValue; }
private:
int myValue;
};
here myValue is accessed before it it declared. C++ does not usually allow forward references but for class members it allows them. It is the compilers job to remember the definition of mutator and accessor until it sees myValue
On the first pass all the class interface is read and thus when the code for function a is compiled it knows that the function b exists in the class Foo
Section 3.3.7 of the C++ Standard includes, among other rules, the statement that
The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies, default arguments, exception-specifications, and brace-or-equal-initializers of non-static data members in that class (including such things in nested classes).
Basically, this requires that analysis of the mentioned contexts, if they appear inline inside the class definition, is deferred until the entire class definition has been processed just as if you had used an out-of-line definition.
A related rule is found in section 9.2:
A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies,
default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise
it is regarded as incomplete within its own class member-specification.
In Effective C++, 3rd Edition, Page 173~175, Scott Meyers talked of alternatives to virtual functions using the strategy pattern:
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter {
public:
typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
explicit GameCharacter(HealthCalcFUnc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue const
{ return healthFunc(*this) }
...
private:
HealthCalcFunc healthFunc;
};
...
struct HealthCalculator {
int operator()(const GameCharacter&) const
{ ... }
};
...
class EyeCandyCharacter: public GameCharacter {
explicit EyeCandyCharacter(HealthCalcFunc hcf=defaultHealthCalc)
:GameCharacter(hcf)
{ ... }
...
}
...
EyeCcandyCharacter ecc(HealthCalculator());
The last statement is to illustrate how to use a health calculation function object in the constructor of EyeCandyCharacter class.
My question is, the constructor of EyeCandyCharacter class requires some function that takes a parameter compatible with a const GameCharacter& and returns something convertible to an int.
Is this supported/implemented by operator() defined in struct HealthCalculator? I don't quite understand the meaning of this overloaded operator here.
Another question of mine here is that the initializer list in the constructor of the derived class usually only initializes the data members of itself (though I know the base part of the derived class is also intialized implicitly). How come the base class GameCharacter appears in the initializer of derived class EyeCandyCharacter?
In your first question:
My question is, the constructor of EyeCandyCharacter class requires
some function that takes a parameter compatible with a const
GameCharacter& and returns something convertible to an int. ... Is
this supported/implemented by operator() defined in struct
HealthCalculator?
Yes, it is supported. You must know/remember that HealthCalculator is a functor. It implements the operator () to "simulate" the syntax of calling traditional functions. Its operator () takes a const GameCharacter& and returns an int, which is compatible with what EyeCandyCharacter (and subsequently GameCharacter) wants.
In your second question:
How come the base class GameCharacter appears in the initializer of
derived class EyeCandyCharacter?
That initializes the base class of EyeCandyCharacter which is GameCharacter by calling GameCharacter's constructor. Not doing this makes EyeCandyCharacter's constructor call GameCharacter's default constructor, which isn't defined, and therefore will result in an error.
As a sidenote, you can now, in C++11, directly use std::function which have roughly the same functionality as std::tr1::function.
For your second question:
Another question of mine here is that the initializer list in the constructor of the derived class usually only initializes the data members of itself (though I know the base part of the derived class is also intialized implicitly). How come the base class GameCharacter appears in the initializer of derived class EyeCandyCharacter?
No, if your base class does not have default constructor defined, but has other constructors defined instead, you have to call based class constructor to initialize base class members. Since in this case, compile will not generate a default constructor for you. In other words,
the base part of the derived class is NOT always initialized implicitly
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);