1).Why did I get this error? What is the correct syntax?
2).Is there a way to write the same code without using the library "vector"?
#include <vector>
myClass()
{
public:
myClass(int x,int y);
void doThis()
{
//Something
}
}
int main(void)
{
std::vector<myClass>*ex_vector = new std::vector<myClass(5,myClass{10,10});
ex_vector[0]->doThis(); //Error Here
delete []ex_vector;
}
I get this error:
error: base operand of '->' has non-pointer type 'std::vector<myClass>'
The correct syntax is
(*ex_vector)[0].doThis();
Also, you should delete ex_vector; and not delete[] ex_vector; since the type of the new was not a raw array type.
However, there's rarely a good reason to new a std::vector. Just use a plain object.
Related
I am trying to write a chip CPU emulator and implementing its instruction table as a vector of structs where each struct contains a value and a function pointer to a particular operation. My compiler (clang++) however gives me the error:
no operator "=" matches these operands -- operand types are: std::__1::vector<A::someStruct, std::__1::allocator<A::someStruct>> = {...}
and:
no viable overloaded '='
for the line func_table = {{1,&A::func1},{2,&A::func2}};
I'm using the exact same syntax used in a similar project on GitHub but I still get these errors. It only seems to be a problem initialising with structs of non-null function pointers. I'm very new to programming with C++ so i'd love to know what I'm misunderstanding. Below is an example of the header and source file
#include <vector>
class A{
public:
A();
private:
struct someStruct{
int a = 0;
void (*fptr)(void) = nullptr;
};
std::vector<someStruct> func_table;
void func1();
void func2();
};
#include "tutorial.h"
A::A(){
func_table = {{1,&A::func1},{2,&A::func2}}; // two entries here, but the table is 512 long
}
void A::func1(){
// something
}
void A::func2(){
// something else
}
int main(){
A example;
return 0;
}
I don't understand what these errors mean and why brace initialisation seems to have a problem with function pointers. I would really appreciate any input on this. Thanks
The structure definition should look like
struct someStruct{
int a = 0;
void (A::*fptr)(void) = nullptr;
};
because you are trying to use member functions of the class A as initializers.
A::A(){
func_table = {{1,&A::func1},{2,&A::func2}};
}
That is you have to declare pointers to class members.
If I create a class in c++, it is possible to call a function of an object of this class, even if this class does not exists.
For example:
Class:
class ExampleClass
{
private:
double m_data;
public:
void readSomeData(double param)
{
m_data = param;
}
}
Any function where this class is used:
int main()
{
ExampleClass* myClass;
myClass->readSomeData(2.5);
}
Ofcourse this wouldn't function, because myClass is not defined.
To avoid such situations, I check if ExampleClass objects are a null_ptr
example:
void readSomeData(double param)
{
if(this == null_ptr)
return;
m_data = param;
}
But gcc says:
'this' pointer cannot be null in well-defined C++ code; comparison may
be assumed to always avaluate to false.
Ofcourse that is only a warning, but I think it is not nice to have this warning. Is there a better way to check if the pointer of a class is defined?
Testing it in the class is the wrong way, the warning is correct about that if your code is well defined then this must not be null, so the test should happen at the time when you call the member function:
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
if (myClass != nullptr) {
myClass->readSomeData(2.5);
}
return 0;
}
If a pointer must not be null at a certain part of your code then you should do it according to CppCoreGuideline: I.12: Declare a pointer that must not be null as not_null
Micorosoft provides an Guidelines Support Library that has an implementation for not_null.
Or if possible then don't use pointers at all but std::optional.
So a code setup could look like this:
#include <gsl/gsl>
struct ExampleClass {
void readSomeData(double ){}
};
// now it is clear that myClass must not and can not be null within work_with_class
// it still could hold an invalid pointe, but thats another problem
void work_with_class(gsl::not_null<ExampleClass*> myClass) {
myClass->readSomeData(2.5);
}
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
work_with_class(myClass);
return 0;
}
The best way is not use pointers at all:
int main()
{
ExampleClass myClass;
myClass.readSomeData(2.5);
}
That way there's no need for any check, and in fact, checking this inside the function is moot.
If you need nullability, use std::optional instead.
Either don't use pointers as Bartek Banachewicz has pointed out, or properly initialize and check the pointer:
int main()
{
ExampleClass* myClass= 0;
if (myClass)
myClass->readSomeData(2.5);
return 0;
}
Of course you still have to add the instantiation of the object at some point, otherwise the code is nonsense.
I want to initialize an array of pointers the nice way.. Something like
handler[numberOfIndexes] = {&bla, &ble, &bli, &blo , &blu};
But it doens't work this way. I get an error, obviously, because I'm trying to place an array of pointers to functions, in a single pointer to function:
cannot convert ‘<brace-enclosed initializer list>’ to ‘void (A::*)()’ in assignment
So, here's the code for you to test:
#include <iostream>
#include <list>
using namespace std;
class A
{
private:
void first();
void second();
void third ();
// and so on
void(A::*handlers[4])(void);
public:
A();
};
void A::first()
{
}
void A::second()
{
}
void A::third()
{
}
A::A()
{
//this is ugly
handlers[0] = &A::first;
handlers[1] = &A::second;
handlers[2] = &A::third;
//this would be nice
handlers[4] = {&A::first,&A::second,&A::third,0};//in static this would work, because it would be like redeclaration, with the type speficier behind
}
int main()
{
A sup;
return 0;
}
UPDATE:
In Qt this doesn't work.
I get :
syntax error: missing ';' before '}'
And if I change to
A::A() : handlers ({&A::first, &A::second, &A::third, 0})//notice the parentheses
then a this happens
Syntax Error: missing ')' before '{'
Warning: The elements of the array "A :: Handlers" are by default "initialized.
So, what's the problem with Qt?
By this point, you should have understood what I want to do. Just do a nice initialization of the array of pointers.
Thank you.
Just use an actual initialization, not an assignment (arrays cannot be assigned to).
A::A() : handlers {&A::first, &A::second, &A::third, 0} {}
Sorry for the confusing title, basically I have created two classes, one is an object, and the other being a box that contains an array of such objects. so what I want to do is create a function/constructor inside the object class that takes in an array of ints and stores them inside the box. I want to be able to call this function through the box class constructor to initialize these objects. So ive tried something like below but it isnt working at all, since only the first value of the array gets passed through. What am I doing wrong?
#include <iostream>
#include <string>
class object{
string objectName;
int values[];
public:
void createObject(int[]);
}
class Box{
object objects[100];
public:
Box();
}
Box::Box (void){
int array1[2];
int array2[15];
object[1].createObject(array1);
object[2].createObject(array2);
}
Object::Object(int Values[]){
values = Values;
}
You should really use std::vector. The problem with arrays is that they decay to pointers when passed as arguments to functions. As a consequence, If you want to store a private copy of the elements you are forced to use heap-allocated objects and consequently do memory management by hand (with all the pain it causes).
It is much better to rely on data members that permit applying the rule of zero.
Here's a tentative solution:
#include <iostream>
#include <string>
#include <vector>
class object {
public:
object(std::vector<int> const& v, std::string const& object_name): v_(v.begin(), v.end()), object_name_(object_name) {}
private:
std::vector<int> v_;
std::string object_name_;
};
class box {
public:
box(std::vector<object> const& objects): objects_(objects) {};
private:
std::vector<object> objects_;
};
I recommend you instead use a std::vector. Arrays don't really work well being passed to functions. When you define Object::Object(int Values[]) you are simply passing the first element of this array by value. If you were to use vectors, the function would look like this:
Object::Object(std::vector<int> &Values):
values(Values)
{
}
The problem with the code is in your thinking on what the array is. In C++, all an array is, is a memory pointer. The language allows you to pass an index into the array pointer to access whatever chunk of data lives at that index.
Whenever you pass arrays between functions or classes, pass the array name only. It will be interpreted as a pointer, and won't copy any data. When you do this, you must also pass the length of the array.
Granted, most people stick with vector<> because it's easier, takes care of memory leaks (mostly) and is VERY efficient. But I like doing it myself. It's good for you. I would try:
#include <iostream>
#include <string>
class Object
{
string _objectName;
int *_values;
int _myLength;
Object();
~Object();
void createObject(int *pValues, int arrLength);
}
class Box
{
_Object objects[100];
Box();
}
Box::Box(void) {
int array1[2];
int array2[15];
object[1].createObject(array1, 2);
object[2].createObject(array2, 15);
}
Object::Object() {
_values = null_ptr;
_myLength = 0;
}
Object::~Object() {
delete[] _values;
}
void Object::createObject(int *pvalues, int arrLength) {
_myLength = arrLength;
_values = new int[_myLength];
for(int ndx=0; ndx<arrLength; ndx++) {
_values[ndx] = pvalues[ndx];
}
}
-CAUTION-
I just adapted your code you provided, and added some conventions. There are a couple places in the code where I'm not sure what the purpose is, but there you go. This should give you a good head start.
I am trying to initialize my MedList but it's not working. Here's what I'm talking about:
repository.h
#include "../domain/farmacy.h"
#include "../utils/DynamicVector.h"
class Repository{
private:
DynamicVector<Medicine>* MedList; //I made it pointer so it can be dynamic
public:
Repository(); //constructor
repository.cpp
#include "../domain/farmacy.h"
#include "repository.h"
#include "../utils/DynamicVector.h"
#include <stdlib.h>
Repository::Repository(){
this->MedList=new DynamicVector<Medicine>::DynamicVector(); //error
}
DynamicVector.h
template <typename Element> //this is the Dynamic Vector constructor
DynamicVector<Element>::DynamicVector()
{
this->cap=10;
this->len=0;
this->elems=new Element[this->cap];
}
the error above is:
Multiple markers at this line
- no match for 'operator=' in '((Repository*)this)->Repository::MedList = (int*)operator
new(4u)'
- expected type-specifier
- candidate is:
- expected ';'
this is the medicine class
class Medicine{
private:
int ID;
std::string nume;
double concentratie;
int cantitate;
The Dynamic Vector class:
template <typename Element>
class DynamicVector{
private:
Element* elems;
int cap;
int len;
void resize();
void CopyToThis(const DynamicVector& v);
public:
DynamicVector(); //constructor implicit
DynamicVector(const DynamicVector& ); //constructor de copiere
DynamicVector& operator=(const DynamicVector& );
~DynamicVector();
void addElement(Element elem);
Element delElementAtPosition(int pos);
Element getElementAtPosition(int pos);
int getLen();
};
What am I doing wrong? I tried a lot of variants but nothing seems to work. Could you help me?
I think you're confusing c++ syntax for creating object with some other language, e.g. Java or C#.
In c++, a constructor is called simply by declaring the variable:
DynamicVector<Element> medList; // Calls DynamicVector<Element>::DynamicVector()
The new operator in C#, is to dynamically allocate space for a variable, and returns a pointer to the allocated space. To use it here, you'd have to declare Repository::MedList as a pointer type, and initialize it like so:
DynamicVector<Medicine>* MedList; // in repository.h
this->MedList = new DynamicVector<Medicine>(); // in repository.cpp
However, as Andy Prowl pointed out, it is much better to just let the compiler do the memory management for you. To do so, you should completely remove the erroneous line in repository.cpp. Why? Well, when the repository is constructed, the compiler also tries to construct all member objects using their default constructors. This is exactly what you want, so there is no reason to try to alter the compiler's behavior.
Constructor should be:
Repository::Repository(){
this->MedList=new DynamicVector<Medicine>;
}
DynamicVector() calls the constructor for DynamicVector.
DynamicVector::DynamicVector() is a pointer to the address of the constructor function
The chances are your C++ version doesn't allow empty () for constructors.
this->MedList=new DynamicVector<Medicine>::DynamicVector(); //error
should be
this->MedList=new DynamicVector<Medicine>::DynamicVector;
or (The usual way of writing it)
this->MedList=new DynamicVector<Medicine>;
See here for more info.
EDIT. Make sure you have declared the dynamicVector constructor in the class.
Default constructor with empty brackets
Do the parentheses after the type name make a difference with new?