I'm new to C++ and I have a problem with classes.
I got this prototype
class MMA7455 : public Accel
{
public:
MMA7455(uint8_t);
uint8_t accel_get_data(acceleration_t*);
private:
uint8_t accel_data_ready(void);
};
and I want to create an instance of it
MMA7455 accel = MMA7455(0x21);
but the following message appears
In function `global constructors keyed to accel':
sensors.cpp:(.text+0x8): undefined reference to `MMA7455::MMA7455(unsigned char)'
Why it's looking for 'unsigned char' argument? Same message even if I try to implicitly cast the type of constant
MMA7455 accel = MMA7455((uint8_t)0x21);
You probably didn't link your .cpp file containing the constructor definition. "uint8_t" is a typedef for 'unsigned char".
You need to define MMA7455::MMA7455(uint8_t) somewhere in your program, i.e. add a {}-body after the definition in the prototype (or perhaps you just forgot to compile and link the cpp-file containing the definitions for MMA7455.
It looks for unsigned char because uint8_t happens to be a typedef for unsigned char on your system.
uint8_t is a typedef for unsigned char on your platform. The error is a linker error since you haven't provided an implementation for your constructor and is unrelated to the argument being an unsigned char or not.
Related
// foo.hpp file
class foo
{
public:
static const int nmConst;
int arr[nmConst]; // line 7
};
// foo.cpp file
const int foo::nmConst= 5;
Compiler VC 2015 return error:
1>foo.h(7): error C2131: expression did not evaluate to a constant
1> 1>foo.h(7): failure was caused by non-constant arguments or
reference to a non-constant symbol 1> 1>foo.h(7): note: see usage of
'nmConst'
Why? nmConst is static constant with value defined in *.cpp file.
It's possible to use static const int member as an array size, but you'll have to define this member within class in your .hpp file like so:
class foo
{
public:
static const int nmConst = 10;
int arr[nmConst];
};
This will work.
P.S. About the logic behind it, I believe compiler wants to know size of the array member as soon as it encounters class declaration. If you leave static const int member undefined within the class, compiler will understand that you're trying to define variable-length array and report an error (it won't wait to see if you actually defined nmconst someplace).
I am working with a member function that just sets the object's internal orientation to the values given in the argument:
void A::SetOrientation(float a[3]);
In another class, I have the following:
class B
{
public:
RestoreStateTo(A* const o_pA) const
private:
float d_orientation[3];
};
void
B::RestoreStateTo(A* const o_pA) const
{
o_pA->SetOrientation(d_orientation);
}
I get the following compiler error (with Visual Studio 2010):
error C2664: 'void A::SetOrientation(float [])' : cannot convert parameter 1 from 'const float [3]' to 'float []'
I found that I can avoid the issue with o_pA->SetOrientation(const_cast<float *>(d_orientation));, but I'd like to get a better grasp of what is going on.
I would appreciate an explanation as to why the array argument is converted to a const array as well as suggest the right approach to dealing with the error?
Because the prototype of your function void B::RestoreStateTo(A* const o_pA) const says you will not modify any member of B.
Since d_orientation is an attribute of B, it is const in this function.
Your SetOrientation function should take in a const,
void A::SetOrientation(const float a[3]);
Otherwise, it's possible that A::SetOrientation will modify the array you pass in. Because you have "B::RestoreStateTo(A* const o_pA) const", it means that the compiler won't let you pass a pointer to B::d_orientation as a non-const input, because A::SetOrientation has no guarantee not to modify it.
You have declared a const member function, and therefore all the members of this will be treated as const inside that function. So it shouldn't be surprising that d_orientation is treated as const.
It's the same principle that makes this code illegal:
const B* p = ...;
p->d_orientation[0] = 0.0f; // error, assigning member of `const` object
error C2440: '=' : cannot convert from 'const BWAPI::UpgradeType' to 'const BWAPI::Type *'
at this line
this->generalType = type;
what is the problem? since UnitType extends Type shouldn't be permitted?
class CombatEvent {
public:
CombatEvent& setUnitType(const UnitType& type);
const Type* getGeneralType() const;
private:
UnitType unitType;
const Type* generalType;
}
// implementation
CombatEvent& CombatEvent::setUnitType(const UnitType& type) {
this->generalType = type;
this->unitType = type;
return *this;
}
You need to take the address:
this->generalType = &type;
You're assigning a reference to a pointer. Correct code:
this->generalType = &type;
You may have a look at these links
References vs. Pointers
What are the differences between pointer variable and reference variable in C++?
There's a fundamental problem in your use of BWAPI Types.
1. BWAPI::Type is a templated class that contains all the utility functions common among all types. There is no need to use it. There is no way to know if it is a UnitType or UpgradeType, it only contains an integer as the underlying type.
2. There is no need to turn BWAPI Types into pointers or references. The compiler resolves it to an integer, nothing fancy about it. Would you use const int& everywhere in your code?
I am sorry for my newbie question, but I do not know much about C++. Can anybody answer why I get the error "error: a call to a constructor cannot appear in a constant-expression" when compiling following code;
class EliminationWeight
{
public:
typedef double Type;
static const Type MAX_VALUE = __DBL_MAX__;
static const Type MIN_VALUE = -__DBL_MAX__;
};
I use Ubuntu 12.04 and gcc that comes with it. It is not my code and I know that this code probably it works OK 100% (perhaps in older version of gcc or other compiler). Is there a quick way to fix it?
Thanks in advance for any answers, this is actually my first time asking something at SO.
Call to a constructor cannot appear in a constant-expression is a GCC error message which doesn't really make sense to me here. Clang, for instance, accepts your code with some warnings:
test.cpp:31:23: warning: in-class initializer for static data member of type
'const Type' (aka 'const double') is a GNU extension [-Wgnu]
static const Type MAX_VALUE = __DBL_MAX__;
^ ~~~~~~~~~~~
Anyway, initializing double in a class body is non-standard. You should do initialization separately:
class EliminationWeight
{
public:
typedef double Type;
static const Type MAX_VALUE;
static const Type MIN_VALUE;
};
and then in exactly one source file (not a header file):
const EliminationWeight::Type EliminationWeight::MAX_VALUE = __DBL_MAX__;
const EliminationWeight::Type EliminationWeight::MIN_VALUE = -__DBL_MAX__;
In general, you can only initialize static member variables having integral types in class body, although this has been extended in C++ 0x11. See also Initializing const member within class declaration in C++
I just stumbled across this exact same problem. The code we are discussing is part of the Contraction Hierarchies implementation by KIT.
This is the only compilation error given when trying to compile the code with gcc 4.8.
The fix suggested by #vitaut is what is needed to make this work. However, note that there are already the following lines lingering in main.cpp:
// doesn't look nice, but required by the compiler (gcc 4)
...
const EliminationWeight::Type EliminationWeight::MAX_VALUE;
const EliminationWeight::Type EliminationWeight::MIN_VALUE;
If you decide to create an EliminationWeight.cpp file to go along with your EliminationWeight.h and include it in the Makefile, these lines are the reason why you are seeing a different error than mentioned above:
main.cpp:86:31: error: uninitialized const ‘EliminationWeight::MAX_VALUE’ [-fpermissive]
const EliminationWeight::Type EliminationWeight::MAX_VALUE;
^
main.cpp:87:31: error: uninitialized const ‘EliminationWeight::MIN_VALUE’ [-fpermissive]
const EliminationWeight::Type EliminationWeight::MIN_VALUE;
^
The solution is to either remove these lines in main.cpp or use them for the actual initialization. I have gone with the latter and the lines now look like this:
const EliminationWeight::Type EliminationWeight::MAX_VALUE = std::numeric_limits< EliminationWeight::Type >::max();
const EliminationWeight::Type EliminationWeight::MIN_VALUE = -std::numeric_limits< EliminationWeight::Type >::max();
Note that I have used the std::numeric_limits template for the type defined by the EliminationWeight::Type typedef. This means we only need to change that typedef to use a different type.
However, using these in main.cpp mandates that we include the header for the numeric_limits template. It also worked for me without including the header but that is probably because it is included via some other included file. For the purpose of clean code we should include it anyway.
#include <limits>
Also note that C++11 provides a new function lowest for the numeric_limits template meaning you could substitue the last line with the following:
const EliminationWeight::Type EliminationWeight::MIN_VALUE = std::numeric_limits< EliminationWeight::Type >::lowest();
However, the C++ reference on lowest specifies the return value for floating point types as
implementation-dependent; generally, the negative of max()
so I am not sure whether you gain much by using this function. It does give you cleaner looking code but it seems the return value is somewhat unspecified.
I had this problem when I was going to declare and instantiate a static const object of class Time inside a class Alg. It worked when I declare the member variable inside the class and instantiate it out side, like this:
Class Alg {
public:
.
.
static const Time genTime;
.
.
}
const Alg::genTime = Time(0,0,1,0);
This is probably a ridiculously easy question, but I've been searching around for the answer for a while yet can't seem to figure this out. I'm trying to initialize a constant variable constant pointer in a class. Here is the header file:
class Scheduler{
public:
Scheduler();
explicit Scheduler( unsigned long * );
private:
const unsigned long *const thresh;
};
And here is the constructor for the class
Scheduler::Scheduler( unsigned long * threshold ):
thresh(threshold)
{}
When I attempt to compile this code I run into this error:
scheduler.cpp: In constructor ‘Scheduler::Scheduler()’:
scheduler.cpp:3: error: uninitialized member ‘Scheduler::thresh’ with ‘const’ type ‘const long unsigned int* const’
Multiple sources online discussing constant member variables in constructors for member variables point to using initializer lists. I think I'm doing what I'm supposed to, but apparently it's still no good. Can anyone see what's wrong?
You must initialize your constant member in the initialization list of ALL constructors. You are doing it only for the one with an argument. Do it for the default one too, and everything will be fne. In this particular case, either initialize your thresh with 0, or disable the default constructor.
The problem is in the default constructor, it should be
Scheduler::Scheduler() : thresh(0) {}
or not be implemented at all.
Your code works for me (MSVC2010) - as I believe it should. What compiler are you trying this with?
The only complaint a compiler may/should have with the code is a warning that the automatic copy constructor and assignment operator cannot be created because of the const member.