Hi I am trying to do something like the follow.
If have some variables passed from cmd line i.e..
const char * outputtype1
const char * outputtype2
The latter to can be NULL.
I then want to create an instance of a class if outputtype2 is set in command line. How can I have the instance of this class optional. i.e..
if(outputtype2)
{
cats thomas(outputtype2);
}
I then use this later like
thomas.eatfood(whiskers);
This is where it gets upset.Obviously thomas doesnt exist if outputtype2 is null, but why cant I just do this?
if (outputtype2)
{
cats thomas(outputtype2);
}
without error
'thomas' was not declared in this scope. I fear I am missing some fundamental rule here.
You'd probably want boost::optional<cats>. This allows you to define thomas up front, and assign cats(outputtype2) to thomas if and only if it's available.
The consequence is that on any use of thomas, you will have to check it was actually assigned to.
If I understand your question, the problem is that you create the instance of the class in the if scope. Later you try to call the method eatfood of the object thomas but the object doesn't exist in the current scope.
Maybe you want to do this...
if (outputtype2) {
cats thomas(outputtype1);
thomas.eatfood(whiskers);
}
Or use a pointer...
Cats* thomas = NULL;
if (outputtype2) {
thomas = new Cats(outputtype1);
}
if (thomas != NULL) {
thomas->eatfood(whiskers);
}
What you miss is the concept of variable scope and visibility.
When you write :
if(outputtype2)
{
cats thomas(outputtype2);
}
that means that the variable thomas exists only in the block it is declared in. Outside it, thomas doesn't exists anymore, both the object and the reference are destroyed when the control leaves the block. So you cant use them outside!
Find another logic to write your program.
Related
I am writing a game in which one Object has an ability to turn into an object of another class (e.g. Clark Kent -> Superman). I would like to know what is the most efficient way to implement this.
The logic of my current code:
I have created a turnInto() function inside the ClarkKent class. The turnInto function calls the constructor of Superman class, passing all needed infos to it. The next step is to assign the address of Superman object to the current ClarkKent object.
void ClarkKent::turnInto() {
Superman sMan(getName(), getMaxHP(), getDamage());
&(*this) = &w; // <- error here
this->ClarkKent::~ClarkKent();
}
As you might have guessed, the compiler gives an error that the expression is not assignable. Not sure how to find a correct solution to this.
Keep it simple and don't play tricks you don't understand with your objects.
Superman ClartkKent::turnInto() {
return {getName(), getMaxHP(), getDamage()};
}
At the callee:
ClartkKent some_guy{...};
auto some_other_guy = some_guy.tunInto();
Or if you need something fancy:
using NotBatman = std::variant<ClartkKent, Superman>;
NotBatman some_guy = ClartkKent{...};
using std::swap;
swap(some_guy, some_guy.tunInto());
IDK
I have the following object declared in my global scope:
CArrayObj *UpwardMovements = new CArrayObj;
And I want to add CUpwards objects to UpwardMovements. CUpwards inherits from CObject so it is possible to add it to the array. However, I cannot add it to the array in a method.
For instance:
void OnTick()
{
CUpwards *UpMovm = new CUpwards(ColorForUpwards);
UpwardMovements.Clear();
CalcUpwardMovement(UpMovm);
}
void CalcUpwardMovement(CUpwards &pUpMovm)
{
UpwardMovements.Add(pUpMovm);
}
I get:
'pUpMovm' - parameter conversion not allowed
If I do the same in my OnTick() method, it works.
Any help would be greatly appreciated.
Using * vs reference. Last line of OnTick(), change to
CalcUpwardMovement(*UpMovm);
Because that method uses reference.
Edit - 4/8
Weird ... does your compiler want another parenthesis? I'm just guessing. I think it should not need another parenthesis.
Your code, with my proposed fix (see "change here" comment)
void OnTick()
{
CUpwards *UpMovm = new CUpwards(ColorForUpwards);
UpwardMovements.Clear();
CalcUpwardMovement( (*UpMovm) ); // change here <<<<<<<<<<<<
}
void CalcUpwardMovement(CUpwards& pUpMovm)
{
UpwardMovements.Add(pUpMovm);
}
Perhaps you did not mean to use the reference (I see you named the formal parameter 'pUpMovm', but a reference is not a pointer. Did you change your mind one place but not the other?
Perhaps you want UpwardMovements.Add(pUpMovm) to be able to modify the local variable pointer UpMovm in OnTick() ... but in this code that would be pointless as the modified pointer would not be used.
I solved the problem as follows:
UpwardMovements.Add(GetPointer(pUpMovm));
You may want to check the pointer before this operation with CheckPointer(GetPointer(pUpMovm));
could someone please tell me what I need to do in order to create an array of objects in a function (other than in the main function).
I will try to explain by making up some sort of example...
Let's say I have a program named TimeScheduler.cpp that implements the class Schedule.h
(and I have the implementation in a separate file Schedule.cpp where we define the methods).
In the declaration file we have declared two constructors
Schedule(); //the default
and
Schedule(int, int, int);//accepts three arguments
to get to the point--let's say in the main program file TimeScheduler.cpp we created our own functions in this program apart from the functions inherited from the class Schedule. so we have our prototypes listed at the top.
/*prototypes*/
void makeSomeTime();
etc.....
we have
main(){
//etc etc...
}
we then define these program functions
void makeSomeTime(){
//process
}
let's say that inside the function makeSomeTime(), we would like to create an array of Schedule objects like this
Schedule ob[]={
summer(5,14, 49),
fall(9,25,50)
};
what do I have to do to the function makeSomeTime() in order for it to allow me to create this array of objects.
The reason I ask is currently i'm having difficulty with my own program in that it WILL allow me to create this array of objects in main()....but NOT in a function like I just gave an example of. The strange thing is it will allow me to create a dynamic array of objects in the function..... like
Schedule *ob = new Schedule[n+1];
ob[2]= Schedule(x,y,z);
Why would it let me assign to a non-dynamic array in main(), but not let me do that in the function?
This is not correct:
Schedule ob[]={
summer(5,14, 49),
fall(9,25,50)
};
You appear to be trying to introduce 3 new names:
ob, which is an array of Scedules
summer, which is a Schedule
fall, which is a Schedule
You can't introduce summer and fall as new names like that. Perhaps this was just a typo, and you meant:
Schedule ob[]={
Schedule(5,14, 49),
Schedule(9,25,50)
};
...which is perfectly fine, and can exist in a function such as:
void make_schedule()
{
Schedule ob[]={
Schedule(5,14, 49),
Schedule(9,25,50)
};
}
But now you have another problem -- your make_schedule function returns void. The Schedule array you created in make_schedule is created and then just thrown away. If you want to return an array from a functtion, the best thing to do is to use a vector, and return that:
std::vector<Schedule> make_schedule()
{
Schedule ob[]={
Schedule(5,14, 49),
Schedule(9,25,50)
};
const size_t num_obs = sizeof(ob)/sizeof(ob[0]);
std::vector<Schedule> ret;
std::copy( &ob[0], &ob[num_obs], std::back_inserter(ret));
return ret;
}
A poorer alternative is to use dynamic allocation to allocate your array, and return a pointer to the first element. In this case, when using new [] it's important to note that you can only use the default constructor.
I decided that instead of using a vector, I could use an unordered_map. I didn't realize that when you 'name' an object in c++, you aren't really giving it a name...it is simply used as a sort of temporary reference. if you want to use names you are better off using a name as a sort of key value in a set. like:
string foodname;
foodname = "cake";
[foodname, 10.95]
foodname = "bread";
[foodname, 5.75]
I found help with unordered_map on http://msdn.microsoft.com/en-us/library/bb981993.aspx
I am writing an application using the crypto++ library. For those not familiar with it, the ECB_Mode template classes inherit from CipherModeBase. The program compiles and runs, but the output I am getting is incorrect. When I call the encryption method from the cipher_object, it doesn't work the same way as if I use an ECB_Mode object directly. I have verified that the options object instance variables are getting assigned correctly. I would like to create the instances within an if_then_else structure or switch_case so I can keep the code nice and DRY. What am I doing wrong?
Here is what I am trying but doesn't work:
CipherModeBase *cipher_object;
cipher_object == NULL;
if(options->cipher == BS_AES)
{
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
else if(options->cipher == BS_TWOFISH)
{
ECB_Mode<Twofish >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
cipher_object->processData(args);
Here is what does work:
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
ecbEncryption.processData(args);
PS. I know not to use ECB mode. I just don't want to mess with IVs until I can get everything working. I am also relatively inexperienced with C++.
Your ecbEncryption objects are declared on the stack within the if and else scopes. (Scopes are the things enclosed by curly brackets).
An object will be destroyed when the scope it was declared in exits. So, the object you're calling processData on has been deleted before you call that method. Clearly that won't work.
One option is you could declare the objects on the heap instead of the stack. That way the lifetime could be controlled to work the way you want.
Try to use a std::unique_ptr for the cipher_object instead of a raw pointer. Then, in the if and else clauses assign to it like:
cipher_object.reset( new ECB_Mode<AES>::Encryption(options->key, options->keylen) );
Then the object will remain on the heap until the end of the cipher_object's scope, at which point the unique_ptr will delete it for you. And, the cipher_object's scope will last until after you call any methods on it.
Here:
cipher_object == NULL;
if(options->cipher == BS_AES)
{
// v
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
ecbEncryption is local to that scope. You are storing the address of a local, and using it after it goes out of scope. That's undefined behaviour. You should allocate it on the heap using the new keyword:
if(options->cipher == BS_AES)
{
cipher_object = new ECB_Mode<AES >::Encryption(options->key, options->keylen);
}
You should do the same for the other if statement.
Also note that this:
cipher_object == NULL;
Should be changed to this:
cipher_object = NULL;
The problem should be solved using the above code, though.
(Disclaimer: I have removed the Qt tag in case the problem is in my syntax / understanding of the references involved here)
I have a foreach loop with an object Member. When I enumerate through the list and try to access a member field, the debugger stops and I get a message:
Stopped: 'signal-received' -
The assert failure is:
inline QString::QString(const QString &other) : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }
I have checked if the member is NULL, and it isn't. I have tried re-working the code, but I keep failing on this simple call.
Some thing's I missed out. MemberList is a singleton (definitely initialized and returns a valid pointer) that is created as the application launches and populates the MemberList with Members from a file. When this is created, there are definitely values, as I print them to qDebug(). This page is literally the next page. I am unsure as to how the List items can be destroyed.
The code is as follows:
int i = 0;
QList<Member*> members = ml->getMembers();
foreach (Member* mem, members)
{
QString memID = mem->getMemberID(); // Crash happens here
QListWidgetItem *lstItem = new QListWidgetItem(memID, lsvMembers);
lsvMembers->insertItem(i, lstItem);
i++;
}
The Member classes get is as follows:
QString getMemberID() const;
and the actual function is:
QString Member::getMemberID() const
{
return MemberID;
}
The ml variable is received as follows:
QList<Member*> MemberList::getMembers()
{
return MemberList::getInstance()->memberList;
}
Where memberList is a private variable.
Final answer:
I decided to rework the singleton completely and found that I was not instantiating a new Member, rather reusing the previous object over and over. This caused the double reference. S'pose thats pointers for you. Special thanks to Troubadour for the effort!
If mem is not null it could still be the case that the pointer is dangling i.e. the Member it was pointing to has been deleted.
If Member inherits from QObject then you could temporarily change your QList<Member*> that is stored in ml (assuming that's what's stored in ml) into a QList< QPointer<Member> >. If you then get a null QPointer in the list after calling getMembers or at any point during the loop then the object must have been destroyed at some point.
Edit
As regards the singleton, are you sure it's initiliased properly? In other words does MemberList::getInstance() return a valid pointer or just a random uninitialised one?
Edit2
Since we've exhausted most possibilities I guess it must be in the singleton somewhere. All I can suggest is to keep querying the first item in the list to find out exactly where it goes bad.