I am being told that I can't use the 'this' keyword in a class function. I'm coming from c# and i'm used to this working, but the compiler tells me that it can only be used within nonstatic member functions.
D3DXVECTOR3 position;
void Position(D3DXVECTOR3 position)
{
this.position = position;
}
this is a pointer containing the address of the object.
D3DXVECTOR3 position;
void YourClassNameHere::Position(D3DXVECTOR3 position)
{
this->position = position;
}
Should work.
D3DXVECTOR3 position;
void YourClassNameHere::Position(D3DXVECTOR3 position)
{
(*this).position = position;
}
Should also work.
In C++ you need to qualify your Position function with the class name:
void YourClassNameHere::Position(D3DXVECTOR3 position)
Also from #Pubby8's answer this is a pointer, not a reference so you need to use this->position instead (or consider using parameter names that don't shadow class members - I like using trailing _ on my class members).
Also, C++ doesn't pass by reference by default so if D3DXVECTOR3 is a complicated type you'll be copying a lot of data around. Consider passing it as const D3DXVECTOR3& position instead.
Not only is Position a free function (not associated with a class) the way you wrote it, but this is also a pointer, not a reference.
D3DXVECTOR3 position;
void ClassName::Position(D3DXVECTOR3 position)
{
this->position = position;
}
or, if that's supposed to be a constructor,
ClassName::ClassName(D3DXVECTOR3 p) : position(p)
{
}
Related
I want to make an argument for one of the member functions optional. When no argument is provided, it would use an member variable.
However, when I tried to compile it it shows
error: invalid use of non-static data member 'Object::initPos'
Just to isolate the problem, I tried defaulting an int type and it compiled fine.
I wonder what is the problem with my code and how I could use a member function as default value.
Thank you for your help!
Object.h
class Object
{
public:
...
void MoveTo(double speed, Point position);
protected:
Point initPos;
Point currPos;
};
Object.c
void Object::MoveTo(double speed, Point position = initPos)
{
currPos = postion;
}
Point.h
class Point
{
...
private:
double x;
double y;
double z;
};
Default argument expressions for a member function can only depend on things that are in class or global scope. The default argument also has to be specified in the method's declaration (i.e. in the header file).
To get around this, you need 2 overloads of your MoveTo method. One that takes 1 argument, and another that takes 2 arguments. The method taking 1 argument calls the other method, passing along the value that you consider as the default.
void Object::MoveTo(double speed)
{
MoveTo(speed, initPos);
}
void Object::MoveTo(double speed, Point position)
{
// Everything is done here.
}
Note that when you make MoveTo(double) call MoveTo(double, Point), it allows you to write the implementation of MoveTo only once, thereby respecting the DRY principle.
Default values are not part of the prototype, i.e. they're resolved by the caller, not by the function itself. So firstly, they have to be visible to the caller. Secondly, they cannot access protected members of the class. (I'm pretty sure you can't even use public members as defaults, but I'm too tired to check.)
To solve the problem, use chained overloads as suggested in other answers.
You can overload your function member like that:
void Object::MoveTo(double speed, Point position) {
....
}
void Object::MoveTo(double speed) {
Point position = this->initPos;
MoveTo(speed, position);
}
Besides overloading, another approach is passing an invalid value as the default value. Then check it inside your function.
void Object::MoveTo(double speed, Point position = InvalidPosition) {
position = (position != InvalidPosition) ? position : initPos;
...
}
How to make an adapter class to support both const and non-const underlying data appropriately?
Concrete Example
RigidBody is a class describing physic property of object.
Here is its very simplified version (1D):-
class RigidBody{
float position=1;
public: float getPosition()const{ return position;}
public: void setPosition(float ppos){ position=ppos;}
};
Adapter encapsulates RigidBody.
It provides a-little-distorted functionality to get/set position:-
class Adapter{
public: RigidBody* rigid; int offset=2;
public: float getPosition(){
return rigid->getPosition()+offset; //distort
}
public: void setPosition(float ppos){
return rigid->setPosition(ppos-offset); //distort
}
};
I can set position of RigidBody indirectly by using Adapter :-
int main() {
RigidBody rigid;
Adapter adapter; //Edit: In real life, this type is a parameter of many function
adapter.rigid=&rigid;
adapter.setPosition(5);
std::cout<<adapter.getPosition();//print 5
return 0;
}
Everything works (demo).
Objective
I want create a new function that receives constRigidBody* rigid.
I should be able to read from it (e.g. getPosition()) by using adapter.
However, I don't really know how to do it elegantly.
void test(const RigidBody* rigid){
Adapter adapter2;
//adapter2.rigid=rigid; //not work, how to make it work?
//adapter2.setPosition(5); //should not work
//adapter2.getPosition(); //should work
}
My poor solutions
Solution A1 (2 adapters + 1 widget)
Create a widget :-
class AdapterWidget{
public: static Adapter createAdapter(RigidBody* a);
public: static AdapterConst createAdapter(const RigidBody* a);
};
AdapterConst can only getPosition(), while AdapterConst can both get and set.
I can use it like :-
void test(const RigidBody* rigid){
auto adapter=AdapterWidget::createAdapter(rigid);
It is easy to use.
Disadvantage: Code of AdapterConst and Adapter will be very duplicated.
Solution A2 (+inheritance)
It is an improvement of the previous solution.
Let Adapter (has setPosition()) derive from AdapterConst (has getPosition()).
Disadvantage: It is not concise. I use 2 classes for the single task!
This might seem to be trivial, but in a bigger code-base, it is not fun at all.
Specifically, location of getPosition() will be far-away from setPosition(), e.g in different files.
This causes maintainability problem.
Solution B (template)
Create a template class. There are many ways e.g. :-
Adapter<T =RigidBody OR const RigidBody >
Adapter<bool=true is const OR false is non-const >
Disadvantage: In every ways, it is inelegant. It is an overkill. (?)
I will suffer from disadvantage of template e.g. everything in header.
Solution C1 (const_cast)
I am trying to avoid it. It is evil.
class Adapter{
public: RigidBody* rigid;
void setUnderlying(const RigidBody* r){
rigid=const_cast< RigidBody*>(r);
}
....
};
Solution C2 (+manual assert)
I can add some assertion manually.
It just emphasizes how much it is unprofessional :-
bool isConst;
void setUnderlying(const RigidBody* r){
...
isConst=true;
}
void setUnderlying(RigidBody* r){
...
isConst=false;
}
void setPosition(float a){
if(isConst){ /*throw some exception*/ }
....
}
Solution D (run away)
Lazy : change from test(constRigidBody* rigid) to test(RigidBody* rigid).
Crazy : change RigidBody::setPosition() to be const.
In either way, my program will not be const-correct any more,
but a single Adapter class would be enough.
Question
Do I really have to do one of these things wherever I encounter the const/non-const pattern?
Please provide a pretty solution. (no full code is required, but I don't mind)
Sorry for the long post.
Edit: In real life, Adapter is a parameter for many function.
It is passed around like a toy.
Most of such functions don't have knowledge about RigidBody, so it is not quite suitable to change from a bundle calling someFunction(adapter) to someFunction(offset,rigidbody).
You shouldn't keep with that idea. This is C++, not Java.
Your code is extremely Java oriented. I can see it by the way you write the code, use pointers and silently omit const when needed.
In fact, most of the bad C++ code that I personally saw is pretty much either written to be "C inside classes" or "Java without GC". Both of them are extremely bad ways of writing C++ code.
Your question has an idiomatic solution:
Ditch most of the design patterns. they are useful for languages where object are reference types by default. C++ prefers most of the times to tread object as value types and prefer static polymorphism (templates) rather than run-time polymorphism (inherit + override).
Write two classes , one is Adapter and one is ConstAdapter. This is what the standard library already does. every container has different iterator and const_iterator implementation exactly because of that reason. you can either store something by pointer, either by const pointer. It is error prone trying to mix the two. If there were a nice solution for that problem, we wouldn't have two iterator typedefs for each container.
A tightly controlled const_cast looks like a good solution to me:
// Only provides read-only access to the object
struct ConstAdapter {
int offset = 2;
// Constructible from const and non-const RigidBodies
ConstAdapter(RigidBody const *rigid)
: _rigid{rigid} { }
// Read-only interface
float getPosition() {
return rigid()->getPosition() + offset; //distort
}
// Hidden away for consistency with Adapter's API
// and to prevent swapping out an "actually non-const" RigidBody
// for a "truly const" one (see Adapter::rigid()`).
RigidBody const *rigid() const { return _rigid; }
private:
RigidBody const *_rigid;
};
// Inherits read-only functions, and provides write access as well
struct Adapter : ConstAdapter {
// Only constructible from a non-const RigidBody!
Adapter(RigidBody *rigid) : ConstAdapter{rigid} { }
// Write interface
void setPosition(float ppos){
return rigid()->setPosition(ppos-offset); //distort
}
// Here's the magic part: we know we can cast `const` away
// from our base class' pointer, since we provided it ourselves
// and we know it's not actually `const`.
RigidBody *rigid() const {
return const_cast<RigidBody *>(ConstAdapter::rigid());
}
};
Regarding:
Specifically, location of getPosition() will be far-away from setPosition(), e.g in different files.
This causes maintainability problem.
This is a non-issue. C++, unlike Java, allows multiple classes in a single file, and you are in fact encouraged to group such tightly related classes together. The declarations of the functions will be only a handful of lines apart, and their definitions can very well be grouped together in the corresponding .cpp file.
Use references instead of pointers, and let the const-ness propogate to the Adapter. Then you can safely const_cast, as
template <class Rigid>
class Adapter{
Rigid & rigid;
int offset;
public:
Adapter(Rigid & rigid, int offset = 2) : rigid(rigid), offset(offset) {}
float getPosition() const { return rigid.getPosition() + offset; }
void setPosition(float ppos) { rigid.setPosition(ppos - offset); }
};
My first instinct would be to access a RigidBody through an Adaptor and a const RigidBody through a const Adaptor. To achieve this, we use a factory to create the right kind of Adaptor, and in the implementation, we access the underlying RigidBody through an accessor method that (safely) casts only when allowed.
The code:
Start with the private members:
class Adaptor
{
RigidBody const& body;
int offset;
Adaptor(RigidBody body, int offset=2)
: body(body),
offset(offset)
{}
Adaptor(const Adaptor&) = delete;
The constructor is private, so we can only create instances through our factory. And we remove the copy constructor, so we can't create a non-const Adaptor from a const one.
Next, we have our first overloaded pair - the accessor used in the implementation. I've marked it protected, in case you want a range of similar adaptors. It could safely be public if you want, though.
protected:
RigidBody& get_body() { return const_cast<RigidBody&>(body); }
RigidBody const& get_body() const { return body; }
We know that the const_cast is safe, because we only get a non-const Adaptor from a non-const RigidBody, as we see in the other overloaded pair, which is the factory:
public:
static Adaptor *adapt(RigidBody& body, int offset = 2) { return new Adaptor{ body, offset }; }
static Adaptor const *adapt(RigidBody const& body, int offset = 2) { return new Adaptor{ body, offset }; }
From here on, each method is declared const unless it needs to modify the body, just as you'd expect. So, if you have a const Adaptor (which you will if you constructed it from a const RigidBody, you can't call any method that modifies body. And the implementation can't modify body from within any of the const methods.
float getPosition() const
{
// this uses the const get_body()
return get_body().getPosition() + offset;
}
void setPosition(float ppos)
{
// this uses the mutable get_body()
get_body().setPosition(ppos-offset);
}
You can demonstrate the safety by trying to modify body in a const method:
void illegal() const
{
get_body().setPosition(0); // error: passing ‘const RigidBody’ as ‘this’ argument discards qualifiers
body.setPosition(0); // error: passing ‘const RigidBody’ as ‘this’ argument discards qualifiers
}
};
Demo:
With a RigidBody, the adapter allows all operations; with a const RigidBody, the adapter allows only const operations:
#include <memory>
int main()
{
{
RigidBody b;
std::unique_ptr<Adaptor> a{Adaptor::adapt(b)};
a->setPosition(15.);
a->getPosition();
}
{
RigidBody const b;
std::unique_ptr<const Adaptor> a{Adaptor::adapt(b)};
a->setPosition(15.); // error: passing ‘const Adaptor’ as ‘this’ argument discards qualifiers
a->getPosition();
}
}
I got the following class:
class Foo {
private:
static float scale;
public:
static float setScale(float scale);
};
When I am trying to implement setScale like this:
float Foo::setScale(float scale) {
this->scale = scale;
return scale;
}
It throws an error:
Invalid use of 'this' outside of a non-static member function.
I really don't get this since my function is marked static.
I saw some related questions but it didn't answer my question.
So how can I fix this?
I know I can change the names and don't use this but there probably is a solution for this?
EDIT: Also when I implement the function inside the class it still throws the same error.
A static member function is not part of the class. In other words, there is only one instance of it. Notice how you access them using the scope resolution operator(Foo::setscale(1.f);), instead of the member reference operator(Foo.setscale(1.f)), because they are not members of instances of the class.
class Foo
{
public:
void DoSomething();
};
In this example, if I create a Foo f and call f.DoSomething(), what happens is that the compiler actually transforms DoSomething() into DoSomething(Foo* this) where this is the address of f.
However, since static member functions are not part of the class, the compiler does not transform them to take in a this pointer.
P.S. So why have static member functions? For one, you can limit the scope of the function to the class it is declared in.
Thank you for reading.
this pointer is not there in static member functions of class. Change the definition as follows:-
float Foo::setScale(float s) {
Foo::scale = s;
return s;
}
Change the function definition the following way
float Foo::setScale(float scale) {
Foo::scale = scale;
}
static member functions have no implicit parameter this.
In the note of paragraph #2 of section 9.4.1 Static member functions of the C++ Standard there is explicitly written that
2 [ Note: A static member function does not have a this pointer
(9.3.2). —end note ]
Also you have to define the function as having return type void because at least you are returning nothing from the function.
void Foo::setScale(float scale) {
Foo::scale = scale;
}
I am a newbie to C++. I want to declare an object as a private member of another class. Is the instantiation of this object can be done with out the default constructor? A sample code is listed here:
class Vertex{
int i;
public:
Vertex(int j):i(j){};
Vertex(const Vertex & v){i=v.i;};
}
class Test{
Vertex v;
public:
Test(const Vertex & v1){v(v1);}
}
int main()
{//some code here;
Vertex v1(int j=1);
Test(v1); // *error: no matching function for call to 'Vertex::Vertex()'*
return 0;
}
It appears to me once declared an object as a private class member (e.g. Vertex v), the default constructor is immediately sought after. Anyway to avoid this? Thanks a lot.
Vertex v1(int j=1);
This declares a function, v1, which returns a Vertex and takes an int argument. What you want is
Vertex v1(1);
in addition, you need to use initialiser lists as the other answers have shown:
Test(const Vertex & v1) : v(v1) {}
Initialise Test::v just as you initialised Vertex::i. (It being private is entirely irrelevant!)
So, using Test::Test's member initialisation list:
Test(const Vertex & v1) : v(v1) {};
For consistency, then, I would also suggest:
Vertex(const Vertex & v) : i(v.i) {};
Initialise members wherever you can.
Use the constructor initialization list:
Test(const Vertex & v1) : v(v1) {}
Once you're in the constructor's body (between the { and }), all data members have been initialized. If you don't do it explicitly, they get default initialized, which requires an available default constructor for user defined types.
Next, you are declaring a function here:
Vertex v1(int j=1);
What you probably meant is
Vertex v1(1);
I want to make an argument for one of the member functions optional. When no argument is provided, it would use an member variable.
However, when I tried to compile it it shows
error: invalid use of non-static data member 'Object::initPos'
Just to isolate the problem, I tried defaulting an int type and it compiled fine.
I wonder what is the problem with my code and how I could use a member function as default value.
Thank you for your help!
Object.h
class Object
{
public:
...
void MoveTo(double speed, Point position);
protected:
Point initPos;
Point currPos;
};
Object.c
void Object::MoveTo(double speed, Point position = initPos)
{
currPos = postion;
}
Point.h
class Point
{
...
private:
double x;
double y;
double z;
};
Default argument expressions for a member function can only depend on things that are in class or global scope. The default argument also has to be specified in the method's declaration (i.e. in the header file).
To get around this, you need 2 overloads of your MoveTo method. One that takes 1 argument, and another that takes 2 arguments. The method taking 1 argument calls the other method, passing along the value that you consider as the default.
void Object::MoveTo(double speed)
{
MoveTo(speed, initPos);
}
void Object::MoveTo(double speed, Point position)
{
// Everything is done here.
}
Note that when you make MoveTo(double) call MoveTo(double, Point), it allows you to write the implementation of MoveTo only once, thereby respecting the DRY principle.
Default values are not part of the prototype, i.e. they're resolved by the caller, not by the function itself. So firstly, they have to be visible to the caller. Secondly, they cannot access protected members of the class. (I'm pretty sure you can't even use public members as defaults, but I'm too tired to check.)
To solve the problem, use chained overloads as suggested in other answers.
You can overload your function member like that:
void Object::MoveTo(double speed, Point position) {
....
}
void Object::MoveTo(double speed) {
Point position = this->initPos;
MoveTo(speed, position);
}
Besides overloading, another approach is passing an invalid value as the default value. Then check it inside your function.
void Object::MoveTo(double speed, Point position = InvalidPosition) {
position = (position != InvalidPosition) ? position : initPos;
...
}