I need to call my public member. The Constructor that takes 1 paramater.
This is how my code looks:
// main
char tmpArray[100] = {};
while ( !inFile.eof() )
{
for ( unsigned x = 0; x < str2.length(); x++ )
{
if ( !isspace( str2[x] ) || isspace( str2[x] ) )
{
tmpArray[x] = str2[x]; // prepare to supply the constructor with each word
ClassObject[wrdCount] = new ClassType[x] ;
//ClassObject[wordCount]->ClassType( tmpArray );
}
}
}
The error is:
'function-style cast' : illegal as
right side of '->' operator
To try and resolve the issue i try two equivalent expressions:
/* no good */ (*ClassObject[wrdCount]).ClassType( tmpArray );
/* no good */ (*ClassObject[wrdCount][10]).ClassType( tmpArray );
/* combine */ ClassObject[arbitrary][values]->ClassType( tmpArray );
Intellisense does brings up all my members and privates except the constructor..
Could this be the reason?
//MyHeader.h
class ClassObject
{
private:
const char* cPtr;
float theLength;
public:
ClassObject( const char* ); // Yes its here and saved..
ClassObject(); // an appropriate default constructor
~ClassObject( );
char GetThis( );
char* GetThat( );
}
I am assuming the following things as it is not clear from the code posted:
(1). ClassObject is defined like this: ClassType* ClassObject[/some value/10];
(2). The class definition in MyHeader.h is of ClassType and not of ClassObject.
In such a case, the following statement is the problem:
ClassObject[wrdCount] = new ClassType[x]
Here it creates 'x' number of ClassType objects. I don't think thats what you want. I guess you want to construct a ClassType object by passing const char* as the constructor parameter. If that is so you should use it like this:
ClassObject[wrdCount] = new ClassType(tmpAray);
Also note that you are assuming size of the array passed. I suggest it is better to use something like a std::string instead of raw character arrays.
I'm not entirely clear on what you're doing, but you cannot explicitly call a constructor like that. If you have a pointer-to-a-pointer-to-a-ClassType called ClassObject, you need to do something like this to initialize it:
ClassObject[wrdCount] = new ClassType*[x]; // create a new 'row' in the array with x columns
for (int i = 0; i < x; ++i) // initialize each 'column' in the new row
ClassObject[wrdCount][i] = new ClassType(tmpArray);
This doesn't seem to make much sense given the code you have pasted though (since wrdCount doesn't change). It's hard to say without an exact problem description.
You need to use identifiers. The following:
ClassObject[wrdCount] = new ClassType[x] ;
tries to apply the operator[] to a class type name. What good can that do? None. Try:
ClassObject *a = new ClassType[x];
This'd create an object a of type array of size x of Classtypes. Do you need an array here -- it's upto you. If all you need is a single variable use:
ClassObject *a = new ClassType;
Related
for (int i = g, x=0; i < counter - 1 && x < 99; i++,x++){
std::string point = std::to_string(i);
std::string pointx = std::to_string(point_vec[i].x);
std::string pointy= std::to_string(point_vec[i].y);
TiXmlElement* P = new TiXmlElement( point );
TiXmlText* X = new TiXmlText(pointx);
doc.LinkEndChild(X);
TiXmlText* Y = new TiXmlText(pointy);
doc.LinkEndChild(Y);
doc.LinkEndChild(P);
}
Above is my example code which I am trying to work on right now, my issue is that it tells me the following:
"error: no matching function for call to 'TiXmlElement::TiXmlElement(std::_cxx11::string&)" this is using wxwidgets on c++, the idea behind using tinyxml is to be able to store the arrays and reuse them after.
Solvved this : I had to go into tinyxml.h and add this at the top : #define TIXML_USE_STL
There are two constructors for string/char type as below:
TiXmlElement::TiXmlElement (const char * _value)
or
#ifdef TIXML_USE_STL
TiXmlElement::TiXmlElement( const std::string& _value )
So you have to define TIXML_USE_STL if you want to use std::string else use const char *
Refer the tinyxml.cpp
As described, there is no matching function to TiXmlElement(std::_cxx11::string&) which as I understand correctly is some string class from c11 standarisation. In this case it will be exactly point string. Try to check if there is a way of using strings that are meant for TiXmlElement as obviously, as the error is saying, you're providing an instance of wrong class std::_cxx11::string&
How do I initialize an array of objects from a function? I'm aware the code below is impractical; I'm just teaching myself C++.
Here is a structure that contains data.
struct pointStruct {
int numberPoints;
Point2D pointArray;
};
The Point2D class has instance variables x and y. In a separate function, I have:
void setPoints(void) {
pointStruct myPointData;
myPointData.numberPoints = 4;
myPointData.pointArray[4]; // here is the problem
// loop with i
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
I'm trying to initialize the array so that I can loop through it and set the x,y coordinates. I've tried using new and some other methods but I can't work through what I need to do. How can I fix this?
When I try to compile this code, I get the error "no match for 'operator[]' in 'myPointData.pointStruct::pointArray[4]' "
You should probably use std::vector like MadScienceDreams suggests.
However, if you want to learn about such things, you could use a pointer instead. For example:
struct pointStruct {
int numberPoints;
Point2D* pointArray;
};
void setPoints(void) {
pointStruct myPointData;
const int num_points = 4;
myPointData.numberPoints = num_points;
myPointData.pointArray = new Point2D[num_points];
for(int i = 0; i < num_points; ++i) {
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
// Do stuff with myPointData...
// Don't forget to have a "delete" for every "new" when you're done.
delete[] myPointData.pointArray;
}
Point2D pointArray;
pointArray is a single instance to Point2D. It is not an array of instances in which case it's type is Point2D [N].
myPointData.pointArray[4];
The above statement calls operator [] taking a parameter of type int, which is not you actually want. Since there is no such member function in Point2D, compiler complains. If you wish to create array of instances, use std::vector<Point2D>.
Is it possible to set a member attribute in a "generic" way?
I am still new to c++ and just dived into templates, if this is the way to go?
The class i have to use has around 20 string members to be filled from informix database and i could loop through an array with the field(=attribute) names.
Let's say i have a simple class
class Foo
{
public:
attr1
attr2
Foo() { };
~Foo();
}
and i could use it like that:
Foo foo;
string myattr = "attr1";
string myval = "val x1";
string myval = "val x2";
setattribute( foo, myattr, myval1 ); // pseudocode... possible somehow?
cout << foo.attr1; // prints "val x1"
setattribute( foo, myattr, myval2 ); // pseudocode... possible somehow?
cout << foo.attr1; // prints "val x2"
The method i call in the loop could look like this...
// its_ref : empty string reference
// row: ptr on the current db row = query result object
// colname: the db column = attribute
// ki: the object
void get_fd( ITString & its_ref, ITRow * row, ITString colname, ns4__SOAPKunde& ki ) {
ITConversions *c;
ITValue *v = row->Column( colname );
v->QueryInterface(ITConversionsIID, (void **) &c);
c->ConvertTo( its_ref );
// here is the place i want to use it :
setattribute( ki, colname, its_ref.Data() );
}
You can use member data pointers. These can be of any type- e.g.
struct x {
int y;
int z;
};
int main() {
int x::* res = &x::y;
}
However, if you want to start accessing them by identifier at runtime, you will have to build your own system from scratch.
The only option I can think of would be to store you attributes in a map of boost::any. With the assumption that you want your attributes to be of heterogeneous types.
The basic idea is to replace your attributes in Foo with map. So instead of having all your private attributes you would have a map that wraps them. The problem with C++ is that your attribute names don't exist after compiling the program (unlike other scripted languages like python). So there is no way to access an attribute variable from a string representing it's name without using some kind of data structure
removed old edit_
You could use a std::map.
The (base) class of 'ki' then has to implement setattribute like this:
// Member variable of MyClass
std::map<string, string> mProps;
void MyClass::setattribute( const char * name, const char * value )
{
mProps[name] = value;
}
Just when I thought I had it figured out, I get an exception handling error. Problem: The problem is that the private members lose the information outside of the constructor. Here's my class definition
Code:
class ClassType
{
private:
char *cPointer;
int length;
public:
ClassType();
// default constr. needed when allocating in main.
ClassType( const ClassType* );
char otherFunc();
};
classtype.cpp:
"#include ClassType.h"
ClassType( const ClassType* )
{
cPointer = ClassType->cPointer;
length = ClassType->length;
}
ClassType::ClassType( const char *myVar )
{
cPointer = new char[ strlen( myVar ) + 1 ] //+1 for trailing '\0'
strcpy( cPointer, myVar );
length = strlen( cPointer );
}
char ClassType::otherFunc()
{
cPointer; // Nothing is shown when debugging..
cPointer = "MyPointer"; // Results in acrash
length = 5; // Results in a crash
}
// The main function is working properly.
This isn't valid C++ code.
If you are using C++, shouldn't you
use std::string for the string?
Constructor based on another
instance should be ClassType(const
ClassType& rhs)
I can't think of why it would crash where you indicate, but there are several problems with your code (some of which are compile-time problems, so we can't be sure this code accurately reflects the problem):
there are ownership problems - when ClassType::ClassType( const ClassType* ) is called, which instance of ClassType owns the object pointed to by cPointer?
there's no dtor to release the memory allocated in `ClassType::ClassType( const char *myVar )'
since cPointer may point to something allocated by new or might not, you'll have issues trying to determine when the thing allocated by new should be deleted.
As far as the compile time errors go:
the definition of ClassType( const ClassType* ) should start with ClassType::ClassType( const ClassType* )
the contents of ClassType::ClassType( const ClassType* ) should be using a parameter instead of the ClassType class name as the pointer
char ClassType::otherFunc() needs a return statement
Is this the real code?
ClassType( const ClassType* )
{
cPointer = ClassType->cPointer;
length = ClassType->length;
}
If so, it needs to be like this:
ClassType( const ClassType* rhs )
{
cPointer = rhs->cPointer;
length = rhs->length;
}
Also, this constructor is not the default ctor:
ClassType( const ClassType* ); // default constr. needed when allocating in main.
A default ctor is specifically a ctor that either takes zero parameters or all the parameters have defaults specified. In other words, a default ctor is a ctor that can be called like this:
ClassType myObject;
I provided a pretty complete answer in your other question about this code. I believe that the main issue is that your copy constructor is massively broken. It will cause double free errors and other badness. Also since your destructor calls delete on the pointers you allocate, you can't ever assign string literals to your classes pointers.
Default constructors are those for which all the arguments have default values, so your constructor that takes a pointer is not a default constructor.
Your crash locations indicate the class has not been constructed properly, so you're probably getting address errors when you assign to them.
Could you post main, as that is probably key to see the problem?
Is it possible to declare a variable in c++ without instantiating it? I want to do something like this:
Animal a;
if( happyDay() )
a( "puppies" ); //constructor call
else
a( "toads" );
Basially, I just want to declare a outside of the conditional so it gets the right scope.
Is there any way to do this without using pointers and allocating a on the heap? Maybe something clever with references?
You can't use references here, since as soon as you'd get out of the scope, the reference would point to a object that would be deleted.
Really, you have two choices here:
1- Go with pointers:
Animal* a;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
// ...
delete a;
or with a smart pointer
#include <memory>
std::unique_ptr<Animal> a;
if( happyDay() )
a = std::make_unique<Animal>( "puppies" );
else
a = std::make_unique<Animal>( "toads" );
2- Add an Init method to Animal:
class Animal
{
public:
Animal(){}
void Init( const std::string& type )
{
m_type = type;
}
private:
std:string m_type;
};
Animal a;
if( happyDay() )
a.Init( "puppies" );
else
a.Init( "toads" );
I'd personally go with option 2.
You can't declare a variable without calling a constructor. However, in your example you could do the following:
Animal a(happyDay() ? "puppies" : "toads");
You can't do this directly in C++ since the object is constructed when you define it with the default constructor.
You could, however, run a parameterized constructor to begin with:
Animal a(getAppropriateString());
Or you could actually use something like the ?: operator to determine the correct string.
(Update: #Greg gave the syntax for this. See that answer)
I prefer Greg's answer, but you could also do this:
char *AnimalType;
if( happyDay() )
AnimalType = "puppies";
else
AnimalType = "toads";
Animal a(AnimalType);
I suggest this because I've worked places where the conditional operator was forbidden. (Sigh!) Also, this can be expanded beyond two alternatives very easily.
If you want to avoid garbage collection - you could use a smart pointer.
auto_ptr<Animal> p_a;
if ( happyDay() )
p_a.reset(new Animal( "puppies" ) );
else
p_a.reset(new Animal( "toads" ) );
// do stuff with p_a-> whatever. When p_a goes out of scope, it's deleted.
If you still want to use the . syntax instead of ->, you can do this after the code above:
Animal& a = *p_a;
// do stuff with a. whatever
In addition to Greg Hewgill's answer, there are a few other options:
Lift out the main body of the code into a function:
void body(Animal & a) {
...
}
if( happyDay() ) {
Animal a("puppies");
body( a );
} else {
Animal a("toad");
body( a );
}
(Ab)Use placement new:
struct AnimalDtor {
void *m_a;
AnimalDtor(void *a) : m_a(a) {}
~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};
char animal_buf[sizeof(Animal)]; // still stack allocated
if( happyDay() )
new (animal_buf) Animal("puppies");
else
new (animal_buf) Animal("toad");
AnimalDtor dtor(animal_buf); // make sure the dtor still gets called
Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on
Since c++17, there is now an overhead-free way to do this: std::optional. The code in this case would be:
#include <optional>
std::optional<Animal> a;
if (happyDay()) {
a.emplace("puppies");
} else {
a.emplace("toads");
}
The best work around is to use pointer.
Animal a*;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
You can also use std::move:
class Ball {
private:
// This is initialized, but not as needed
sf::Sprite ball;
public:
Ball() {
texture.loadFromFile("ball.png");
// This is a local object, not the same as the class member.
sf::Sprite ball2(texture);
// move it
this->ball=std::move(ball2);
}
...
There is a way to do this without pointers/heap memory, this syntax is just a bit gibberish. Here is an example using std::string. I don't recommend doing this unless you really need the performance.
uint8_t object[sizeof(std::string)];
int main() {
if(true)
new(&object) std::string("Your arguments");
else
new(&object) std::string("Your other arguments");
(*(std::string*)(&object)).append("");
std::cout << (*(std::string*)(&object));
return 0;
}
The annoying part about this is you have to cast object to a string every time you want to use it:
(*(std::string*)(&object))
Yes, you can do do the following:
Animal a;
if( happyDay() )
a = Animal( "puppies" );
else
a = Animal( "toads" );
That will call the constructors properly.
EDIT: Forgot one thing...
When declaring a, you'll have to call a constructor still, whether it be a constructor that does nothing, or still initializes the values to whatever. This method therefore creates two objects, one at initialization and the one inside the if statement.
A better way would be to create an init() function of the class, such as:
Animal a;
if( happyDay() )
a.init( "puppies" );
else
a.init( "toads" );
This way would be more efficient.