I get this error
USCENEComponent = GetComponentRotation : nonstandard syntax. Use & to create a member pointer.
when compiling this code:
if (!Player_isDead) {
FVector fwd = GetActorForwardVector();
FVector muzzle = GetMesh()->GetBoneLocation("pinky_01_r");
muzzle += fwd * 155;
AProjectile* bullet = GetWorld()->SpawnActor<AProjectile>(BPProjectile, muzzle, RootComponent->GetComponentRotation); // <<===== error
if (bullet) {
//bullet->Firer = this;
bullet->ProxSphere->AddImpulse(fwd*BulletLaunchImpulse);
}
else {
GEngine->AddOnScreenDebugMessage(0, 5.f, FColor::Yellow, "no bullet actor could be spawnd. is the bullet overlapping something?");
}
}
What should I add? I don't know offhand. Please let me know in detail. ㅠㅠ
GetComponentRotation is a method. What do you want to do with the method? Call it, or take its address? We don't know, nor does the compiler. It guesses you wanted the address. My guess would be that you wanted to call GetComponentRotation. In that case, add the argument list, even if it's empty: RootComponent->GetComponentRotation( ).
USCENEComponent = GetComponentRotation should be USCENEComponent = GetComponentRotation() (or some variant with an appropriate argument list). GetComponentRoation() is a function call; in C++ you can’t call a function without the parentheses, even if it takes no arguments.
The warning is a bit misleading. It’s really aimed at creating a pointer-to-member-function. Like this:
struct C {
void f();
};
void (C::*pmf)() = &C::f;
That bit on the right-hand-side creates a pointer to the member function f of the struct C.
The business about “non-standard syntax” is a Microsoftism. Any reasonable compiler would tell you that you need parentheses to call a function. The reason that Microsoft gives you this warning is that back in the olden days, Microsoft decided that it made sense to be able to create a pointer to member function without mentioning the class name if the context provided it for you and, while you were being lazy, without the &. So this was legal with Microsoft’s compiler:
struct C {
void f();
void g() { void (C::*pmf)() = f; }
};
They even floated a paper at one of the standards meetings suggesting that the standard should allow this syntax. That didn’t go anywhere.
So, having (erroneously) allowed that syntax, they opted for backward compatibility by giving a misleading warning for code that uses their invalid syntax. Formally, that’s okay: the only requirement that the standard imposes for non-conforming code is that the compiler “issue a diagnostic”, and every compiler I know of considers a warning to be a diagnostic.
So I have a function with a specific signature in a header file, and I want to declare another function with the exact same signature inside a class without typing the parameters again, and of course, hopefully without a macro... The member function should also have an extra hidden parameter obviously, the this pointer (since it's not a static member function).
Now, I'm actually surprised that the following hack/trick works in both GCC and ICC, but I'm not sure if it's "legal" C++. I'm not particularly concerned with legality if it's a supported extension, but unfortunately I do not want it to break on a compiler version update because some people decided to arbitrarily block this useful feature since the standard says "no" (that kind of stuff really annoys me to be honest).
Here's what I mean:
// test.hpp
int func(int x) { return x; }
struct foo
{
decltype(func) fn; // <-- legal?
};
int test()
{
return foo().fn(6);
}
// then in test.cpp
int foo::fn(int x) { return x + 42; }
This works (with GCC and ICC), but I don't know if it's "legal" in the standard. I'm asking just to be assured that it is legal and it won't suddenly stop working in the future.
(if it's not legal and you want to report it as a bug, please mark it as a suggestion to make it a legal compiler extension instead of killing it...)
Basically, it's the same as declaring int fn(int x); in the struct, and that's how it works currently.
If you ask me for a use case: it's to declare a wrapper member function for the other free function which does something with the this pointer before passing it to the free function. Its parameters must match exactly, obviously. Again, I don't want to type the parameters again.
That looks legal; but at definition you have to retype. Consider using perfect forwarding instead.
In C++ the following code gives a compiler error:
void destruct1 (int * item)
{
item->~int();
}
This code is nearly the same, I just typedef the int to another type and something magic happens:
typedef int myint;
void destruct2 (myint * item)
{
item->~myint();
}
Why does the second code work? Does an int get a destructor just because it has been typedefed?
In case you wonder why one ever would like to do this: This comes from refactoring C++ code. We're removing the standard heap and replacing it with selfmade pools. This requires us to call placement-new and the destructors. I know that calling destructors for primitive types is useless, but we want them in the code nevertheless in case we later replace PODs with real classes.
Finding out that naked int's don't work but typedefed ones do was quite a surprise.
Btw - I have a solution that involves template-functions. We just typedef inside the template and everything is fine.
It's the reason that makes your code work for generic parameters. Consider a container C:
template<typename T>
struct C {
// ...
~C() {
for(size_t i = 0; i<elements; i++)
buffer[i].~T();
}
};
It would be annoying to introduce special cases for built-in types. So C++ allows you to do the above, even if T happens to equal to int. The holy Standard says in 12.4 p15:
The notation for explicit call of a destructor can be used for any scalar type name. Allowing this makes it possible to write code without having to know if a destructor exists for a given type.
The difference between using a plain int and a typedef'ed int is that they are syntactically different things. The rule is, that in a destructor call, the thing after the ~ is a type-name. int is not such a thing, but a typedef-name is. Look it up in 7.1.5.2.
Say you have a sub class B which inherits from super class A. You want a function that can accept either A or B.
template <typename T>
void someFunc(T* pObj, bool someOtherArg)
{
pObj->AnInheritMethod();
if (pObj->IsASub())
{
pObj->ANonInhertMethod();
}
}
When I compile this (Visual Studio 6) I get:
error C2065: 'pObj' : undeclared identifier
Am I way off base here?
You don't need a function template for this; the following will do just fine:
void someFunc(A* pObj)
{
pObj->AnInheritMethod();
if (B* pObjAsB = dynamic_cast<B*>(pObj))
{
pObjAsB->ANonInheritMethod();
}
}
Or, if you prefer to use your IsASub() member function instead of dynamic_cast:
void someFunc(A* pObj)
{
pObj->AnInheritMethod();
if (pObj->IsASub())
{
B* pObjAsB = static_cast<B*>(pObj);
pObjAsB->ANonInheritMethod();
}
}
Aside from the missing return type, I don't see anything obviously wrong with the code in your example; I don't have Visual C++ 6 installed to check.
You don't need templates for that, that is a free behaviour courtesy of polymorphism.
Edit: also if you write something like:
if (pObj->IsASub())
then there's maybe something wrong in your design. The method is supposed to work for any type in the derivation chain.
You're asking a question that is completely unrelated to the code and error that you included.
In order to have a function take an A or a class derived from A, all it needs to do is take a pointer or reference to A, e.g.
someFunc(A* pObj, bool someOtherArg);
or
someFunc(A& obj, bool someOtherArg);
It will work by virtue of inheritance. That's kind of the whole point of deriving classes from each other. The way you have written it with templates, it will work with any class that defines the three methods you use, whether or not it derives from A.
Now the error you posted is unrelated to this question but is bizarre. There's nothing wrong with the code you posted, but Visual Studio 6 is an ancient compiler; it's twelve years old and does not fully support modern ISO standard C++. This error may be an artifact of a sub-standard templating implementation in the compiler.
This question already has answers here:
When should I make explicit use of the `this` pointer?
(12 answers)
Closed 6 years ago.
I'm dealing with a large code base that uses the following construct throughout
class MyClass
{
public:
void f(int x);
private:
int x;
};
void MyClass::f(int x)
{
'
'
this->x = x;
'
'
}
Personally, I'd always used and hence prefer the form
class MyClass
{
public:
void f(int x);
private:
int _x;
};
void MyClass::f(int x)
{
'
'
_x = x;
'
'
}
The reasons I prefer the latter are that it is more succinct (less code = fewer potential bugs), and that I don't like having multiple variables of the same name in scope at the same time where I can avoid it. That said, I am seeing the former usage more and more often these days. Is there any upside to second approach that I am unaware of? (e.g. effect on compile time, use with templated code, etc...) Are the advantages of either approach significant enough merit a refactor to the other? Reason I ask, that while I don't like the second approach present in the code, the amount of effort and associated risk of introducing further bugs don't quite merit a refactor.
Your version is a bit cleaner, but while you're at it, I would:
Avoid leading underscore: _x is ok until somebody chooses _MyField which is a reserved name. An initial underscore followed by a capital letter is not allowed as a variable name. See: What are the rules about using an underscore in a C++ identifier?
Make the attribute private or protected: the change is safe if it compiles, and you'll ensure your setter will be used.
The this-> story has a use, for example in templated code to make the field name dependent on your type (can solve some lookup issues).
A small example of name resolutions which are fixed by using an explicit this-> (tested with g++ 3.4.3):
#include <iostream>
#include <ostream>
class A
{
public:
int g_;
A() : g_(1) {}
const char* f() { return __FUNCTION__; }
};
const char* f() { return __FUNCTION__; }
int g_ = -1;
template < typename Base >
struct Derived : public Base
{
void print_conflicts()
{
std::cout << f() << std::endl; // Calls ::f()
std::cout << this->f() << std::endl; // Calls A::f()
std::cout << g_ << std::endl; // Prints global g_
std::cout << this->g_ << std::endl; // Prints A::g_
}
};
int main(int argc, char* argv[])
{
Derived< A >().print_conflicts();
return EXIT_SUCCESS;
}
Field naming has nothing to do with a codesmell. As Neil said, field visibility is the only codesmell here.
There are various articles regarding naming conventions in C++:
naming convention for public and private variable?
Private method naming convention
c++ namespace usage and naming rules
etc.
This usage of 'this' is encouraged by Microsoft C# coding standards. It gives a good code clarity, and is intended to be a standard over the usage of m_ or _ or anything else in member variables.
Honestly, I really dislike underscore in names anyway, I used to prefix all my members by a single 'm'.
A lot of people use this because in their IDE it will make a list of identifiers of the current class pop up.
I know I do in BCB.
I think the example you provide with the naming conflict is an exception. In Delphi though, style guidelines use a prefix (usually "a") for parameters to avoid exactly this.
My personal feeling is that fighting an existing coding convention is something you should not do. As Sutter/Alexandrescu puts it in their book 'C++ coding conventions': don't sweat the small stuff. Anyone is able to read the one or the other, whether there is a leading 'this->' or '_' or whatever.
However, consistency in naming conventions is something you typically do want, so sticking to one convention at some scope (at least file scope, ideally the entire code base, of course) is considered good practice. You mentioned that this style is used throughout a larger code base, so I think retrofitting another convention would be rather a bad idea.
If you, after all, find there is a good reason for changing it, don't do it manually. In the best case, your IDE supports these kind of 'refactorings'. Otherwise, write a script for changing it. Search & replace should be the last option. In any case, you should have a backup (source control) and some kind of automated test facility. Otherwise you won't have fun with it.
Using 'this' in this manner is IMO not a code smell, but is simply a personal preference. It is therefore not as important as consistency with the rest of the code in the system. If this code is inconsistent you could change it to match the other code. If by changing it you will introduce inconsistency with the majority of the rest of the code, that is very bad and I would leave it alone.
You don't want to ever get into a position of playing code tennis where somebody changes something purely to make it look "nice" only for somebody else to come along later with different tastes who then changes it back.
I always use the m_ naming convention. Although I dislike "Hungarian notation" in general, I find it very useful to see very clearly if I'm working with class member data. Also, I found using 2 identical variable names in the same scope too error prone.
I agree. I don't like that naming convention - I prefer one where there is an obvious distinction between member variables and local variables. What happens if you leave off the this?
class MyClass{
public:
int x;
void f(int xval);
};
//
void MyClass::f(int xval){
x = xval;
}
In my opinion this tends to add clutter to the code, so I tend to use different variable names (depending on the convention, it might be an underscore, m_, whatever).
class MyClass
{
public:
int m_x;
void f(int p_x);
};
void MyClass::f(int p_x)
{
m_x = p_x;
}
...is my preferred way using scope prefixes. m_ for member, p_ for parameter (some use a_ for argument instead), g_ for global and sometimes l_ for local if it helps readability.
If you have two variables that deserve the same name then this can help a lot and avoids having to make up some random variation on its meaning just to avoid redefinition. Or even worse, the dreaded 'x2, x3, x4, etc'...
It's more normal in C++ for members to be initialised on construction using initialiser.
To do that, you have to use a different name to the name of the member variable.
So even though I'd use Foo(int x) { this.x = x; } in Java, I wouldn't in C++.
The real smell might be the lack of use of initialisers and methods which do nothing other than mutating member variables, rather than the use of the this -> x itself.
Anyone know why it's universal practice in every C++ shop I've been in to use different names for constructor arguments to the member variables when using with initialisers? were there some C++ compilers which didn't support it?
I don't like using "this" because it's atavistic. If you're programming in good old C (remember C?), and you want to mimic some of the characteristics of OOP, you create a struct with several members (these are analogous to the properties of your object) and you create a set of functions which all take a pointer to that struct as their first argument (these are analogous to the methods of that object).
(I think this typedef syntax is correct but it's been a while...)
typedef struct _myclass
{
int _x;
} MyClass;
void f(MyClass this, int x)
{
this->_x = x;
}
In fact I believe older C++ compilers would actually compile your code to the above form and then just pass it to the C compiler. In other words -- C++ to some extent was just syntactic sugar. So I'm not sure why anyone would want to program in C++ and go back to explicitly using "this" in code -- maybe it's "syntactic Nutrisweet"
Today, most IDE editors color your variables to indicate class members of local variables. Thus, IMO, neither prefixes or 'this->' should be required for readability.
If you have a problem with naming conventions you can try to use something like the folowing.
class tea
{
public:
int cup;
int spoon;
tea(int cups, int spoons);
};
or
class tea
{
public:
int cup;
int spoon;
tea(int drink, int sugar);
};
I think you got the idea. It's basically naming the variables different but "same" in the logical sense. I hope it helps.