I'm writing a somewhat toy program to get into c++. However I'm having quite a lot of trouble with a segmentation fault at a very specific line in my code. I know that the segmentation fault means I tried to access memort that was not given to my program.
The code is (somewhat) as follows(it's actually too big to just copy paste) :
class car {
protected:
int speed;
std::string brand;
public:
car (int s, std::string b):speed(s),brand(b) {
std::cout << "New car has been created" << endl;
}
virtual int is_stopped () {
if (speed==0) return 1;
else return 0;
}
virtual void speed_up () {
speed++;
}
car* clone () {
car* tmp(this);
return tmp;
}
};
class fast_car : public car {
public:
fast_car (int s, std::string b):car(s,b) { }
};
class slow_car : public car {
public:
slow_car (int s, std::string b):car(s,b) { }
};
class highway {
int number_of_cars;
car **first; //There are derived classes from car hence the double pointer
public:
highway (int c, int s, std::string b):number_of_cars(c) {
first = new car*[c];
for (int i=0;i<c/2;i++)
first[i] = new fast_car (s,b);
for (int i=c/2;i<c;i++)
first[i] = new slow_car (s,b);
}
void speed_up () {
int pos;
pos = rand()%number_of_cars; //give me a random number between 0 and number_of_cars;
if (pos!=0) pos--; //We don't want position -1
first[pos]->speed_up ();
clone_fast (first[pos], (number_of_cars - pos - 1)); //the second argument is the remaining array "spots" until the end of the array
}
void clone_fast (car* cur, int rem) {
car* tmp;
for (int i=-;i<=rem;i++)
if ((cur+1)->is_stopped ()) { //Exact line where I get the segmentation fault
tmp = cur->clone ();
cur++;
}
}
};
So there it is. I tried to give you everything I could to recreate the problem. I'll try to solve any further questions.
Any help would be greatly appreciated.
The car*s are created by new, and aren't necessarily contiguous; they certainly aren't arrays that you can pointer-arithmetic around with. (car*) + 1 is not the same as (car**)[i + 1] (which is more like (car**) + 1). You probably want something a bit more like (*(first + 1))->doThing(), not (first[X] + 1)->doThing().
Edit: to be a bit more clear, if you can't do car[X + 1], then you can't do *(car + 1). Since the cars in clone_fast() are object pointers and not arrays, you can't do car[X + 1], thus (cur + 1)->is_stopped() is wrong.
I would suggest removing all pointer crap, and use more modern idioms. You can expand on the code below. However, it is unclear to me why you have two derived classes: they have no specific data neither methods, so why ?
class car
{
private:
int speed;
std::string brand;
public:
car (int s, std::string b):speed(s),brand(b)
{
std::cout << "New car has been created" << endl;
}
bool is_stopped ()
{
return speed==0;
}
void speed_up ()
{
speed++;
}
};
class fast_car : public car
{
public:
fast_car (int s, std::string b):car(s,b) {}
};
class slow_car : public car
{
public:
slow_car (int s, std::string b):car(s,b) {}
};
class highway
{
private:
std::vector<std::shared_ptr<car>> v_cars;
public:
highway (int c, int s, std::string b):number_of_cars(c)
{
for (int i=0;i<c/2;i++)
v_cars.push_back( std::make_shared<fast_car>(s,b) );
for (int i=c/2;i<c;i++)
v_cars.push_back( std::make_shared<slow_car>(s,b) );
}
};
int main()
{
highway h( 50, 20 );
return 0;
}
Related
This has been driving me insane for hours - I'm new to C++: I can't figure out why my programs thinks I want it do this.
I have a class House
class House{
private:
int number;
std::string family;
public:
House(int n, std::string f){
this->number = n;
this->family = f;
}
House(){
this->number = 0;
this->family = "unassigned";
}
void whoLivesHere(){
std::cout<<"The"<<family<<"lives here."<<std::endl;
}
};
I have another class Neighborhood
class Neighborhood{
private:
int size;
House houses[100];
public:
Neighborhood(){
this->size=0;
}
void addHouse(House h){
this->houses[this->size] = h;
this->size++;
}
void whoLivesHere(){
for(int i=0; i<this->size; i++){
this->houses[this->size].whoLivesHere();
}
}
};
And this is what is happening on my main.
int main(){
Neighborhood n1;
House h1(1,"Johnsons");
House h2(1,"Jones");
n1.addHouse(h1);
n1.addHouse(h2);
n1.whoLivesHere();
return 0;
}
And what I get on the Terminal is this.
The unassigned lives here
The unassigned lives here
The unassigned lives here
Why didn't the new objects replace the first two default objects?
Why show three objects? If size should be 1.
Thank you tonnes in advance!
You can make short work of this problem by using the tools the C++ Standard Library gives you, like this:
#include <string>
#include <vector>
#include <iostream>
int main() {
std::vector<House> neighborhood;
// emplace_back() forwards arguments to the constructor
neighborhood.emplace_back(1, "Johnson");
neighborhood.emplace_back(2, "Jones");
// No need to track size, std::vector does that for you: size(),
// but that's not even needed to iterate, you can just do this:
for (auto& house : neighborhood) {
house.whoLivesHere();
}
return 0;
}
Here I've cleaned up your House implementation:
class House {
private:
int number;
std::string family;
public:
// Tip: Use constructor lists
House(int n, const std::string& f) : number(n), family(f) { };
// Useful even for defaults
House() : number(0), family("unassigned") { };
// Flag methods that don't modify anything as const
void whoLivesHere() const {
std::cout << "The " << family << " lives here at number " << number << "." << std::endl;
}
};
I keep getting this error that only virtual functions can be marked as override but the functions in question "norm()" and "string to_string()" are virtual. what could be causing this?
In my main function I am also getting the error no matching member function to call push back, did I make a mistake along the way somewhere and I am just not seeing it?
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
class Group
{
public:
virtual string to_string() = 0;
virtual int norm() = 0;
};
class Real
{
// add your code here
protected:
int number;
public:
Real(int num)
{
number = num;
}
int norm() override
{
return number;
}
string to_string() override
{
return number;
}
int getNumber() const
{
return number;
}
void setNumber(int number)
{
Real::number = number;
}
};
class Complex : public Real
{
// add your code here
protected:
int imaginary;
public:
Complex(int realNum, int imag) : Real(realNum)
{}
int norm() override
{
return sqrt(number * number + imaginary * imaginary) + 'i';
}
string to_string() override
{
return ::to_string(number) + '+' + ::to_string(imaginary) + 'i';
}
};
class Trinomial : public Complex
{
// add your code here
protected:
int third;
public:
Trinomial(int p1, int p2, int p3) : Complex(p1, p2) {
third = p3;
}
int norm() override {
return sqrt(number * number + imaginary * imaginary + third * third);
}
string to_string() override {
return ::to_string(number) + "x^2+" + ::to_string(imaginary) + "x+" + ::to_string(third);
}
};
class Vector : public Group
{
// add your code here
protected:
vector<int> v;
public:
Vector(int num1, int num2, int num3)
{
v.push_back(num1);
v.push_back(num2);
v.push_back(num3);
}
int norm() override
{
int squared_sum = 0;
for (int i = 0; i < v.size(); i++) {
squared_sum += v[i] * v[i];
}
return sqrt(squared_sum);
}
string to_string() override
{
string str = "[";
for (int i = 0; i < v.size() - 1; i++) {
str += ::to_string(v[i]) + " ";
}
str += ::to_string(v[v.size() - 1]) + "]";
return str;
}
};
int main()
{
vector<Group*> elements;
elements.push_back(new Real{ 3 });
elements.push_back(new Complex{ 3,4 });
elements.push_back(new Trinomial{ 1,2,3 });
elements.push_back(new Vector{ 1,2,3 });
for (auto e : elements)
{
cout << "|" << e->to_string() << "| = " << e->norm() << endl;
}
for (auto e : elements)
delete e;
return 0;
}
A couple of issues here:
The class Real must have inherited from Group so that you could override the functions. That is the reason for the error message.
Secondly the Real::to_string must return a string at the end. You
might convert the integer using std::to_string.
Last but not least the Group must have a virtual destructor for defined behaviour. Read more here: When to use virtual destructors?
In short, you need
#include <string>
class Group
{
public:
// other code
virtual ~Group() = default;
};
class Real: public Group // --> inherited from base
{
// other codes
public:
std::string to_string() override {
return std::to_string(number);
}
};
As a side, please do not practice with using namespace std;
your class real has no parent. so you cant override to_string()
A program that stores a phone company's consumers data in a linked list. At the end it displays the bill for each human. I have the following codes:
class BaseTypeOfContract
{
private:
int minutePrice;
int SMSPrice;
public:
void setminutePrice(int x) { minutePrice = x; }
void setSMSPrice(int x) { SMSPrice = x; }
virtual int calculateBill(int talkedMinutes, int sentSMS) = 0;
int getminutePrice() const { return minutePrice; }
int getSMSPrice() const { return SMSPrice; }
};
class SMSBaseType : public BaseTypeOfContract
{
private:
int freeSMS;
public:
SMSBaseType(int minutePrice, int SMSPrice, int freeSMS)
{
setminutePrice(minutePrice);
setSMSPrice(SMSPrice);
setfreeSMS(freeSMS);
}
public:
void setfreeSMS(int free) { this->freeSMS = free; }
virtual int calculateBill(int talkedMinutes, int sentSMS)
{
int billedSMS = (freeSMS > sentSMS) ? 0 : sentSMS - freeSMS;
return talkedMinutes * getminutePrice() + billedSMS * getSMSPrice();
}
};
class Base : public BaseTypeOfContract
{
public:
Base()
{
setminutePrice(30);
setSMSPrice(10);
}
virtual int calculateBill(int talkedMinutes, int sentSMS) { return talkedMinutes * getminutePrice() + sentSMS * getSMSPrice();}
};
class SMSMax : public SMSBaseType
{
public:
SMSMax() : SMSBaseType(20, 5, 150) {}
};
class MobiNET: public SMSBaseType
{
public:
MobiNET() : SMSBaseType(10, 15, 25) {}
};
Client's class:
class Client
{
public:
std::string name;
std::string phoneNumber;
BaseTypeOfContract* typeOfContract;
int talkedMinutes;
int sentSMS;
Client *next;
public:
Client(){}
Client(std::string n, std::string p, int bp, int ks) : name(n), phoneNumber(p), talkedMinutes(bp), sentSMS(ks) {}
void preSetPlan(std::string s)
{
if (s == "MobiNET")
this->typeOfContract = new MobiNET();
else if (s == "SMSMax")
this->typeOfContract = new SMSMax();
else this->typeOfContract = new Base();
}
std::string getname() const { return name; }
std::string getphoneNumber() const { return phoneNumber; }
void setname(std::string n) { name = n; }
void setphoneNumber(std::string pn) { phoneNumber = pn; }
void settalkedMinutes(int bp) { talkedMinutes = bp; }
void setsentSMS(int SSMS) { sentSMS = SSMS; }
int getBill() const { return this->typeOfContract->calculateBill(talkedMinutes, sentSMS); }
};
I read the data from 2 files. First file contains the name, phone number, type of contract. Second file contains the phone number, talked minutes and sent SMS.
Client* file_read_in()
{
std::ifstream ClientData;
ClientData.open("clients.txt");
Client *first = new Client;
first = NULL;
while (!ClientData.eof())
{
std::string name, phoneNumber, typeOfContract;
ClientData >> name;
ClientData >> phoneNumber;
ClientData >> typeOfContract;
std::ifstream ClientTalkedSent;
ClientTalkedSent.open("used.txt");
while(!ClientTalkedSent.eof())
{
std::string phoneNumber2;
ClientTalkedSent >> phoneNumber2;
if (phoneNumber2 == phoneNumber)
{
int talkedMinutes, sentSMS;
ClientTalkedSent >> talkedMinutes;
ClientTalkedSent >> sentSMS;
Client* tmp = new Client(name, phoneNumber, talkedMinutes, sentSMS);
tmp->preSetPlan(typeOfContract);
tmp->next = NULL;
if (first == NULL)
{
first = tmp;
}
else
{
Client *cond = first;
while (cond->next != NULL) cond = cond->next;
cond->next = tmp;
}
}
}
ClientTalkedSent.close();
}
ClientData.close();
return first;
}
And the main:
int main()
{
Client* first = file_read_in();
while(first != NULL)
{
std::cout << first->getname() << " " << first->getphoneNumber() << " " << first->getBill() << std::endl;
first = first->next;
}
return 0;
}
My problem that I should free the allocated memory but I got on idea how. Which class' destructor should do the dirty job. I would appreciate if someone could use my code, to show how the "destructor inheritance" works.
Sorry for my bad english and thanks for the help. This site helped me alot of times, but for this problem I did not find a solution.
If you have a pointer BaseTypeOfContract* typeOfContract; that is used to point to different derived classes, then BaseTypeOfContract needs to have a virtual destructor for delete typeOfContract to work.
And as Client seems to create the objects pointed to, it also ought to be responsible for cleaning them up. Either by using delete typeOfContract; in its destructor, or by storing a smart pointer to get the work done automatically.
The other part is that each Client stores a pointer to the next Client. That seems like not the best design. In real life it is not at all like each person knowing who is the next person that buys a cell phone in the same store. :-)
You would be much better of with a container, like std::vector<Client>, that would also handle the lifetime of the Client objects.
I have to do a program for college.
I have 3 classes already declared in the statement of the problem.
First class:
class piesa_a{
protected:
int id;
char *tip;
int pret;
};
Second class:
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
};
Third class:
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
};
In main I need to create an array in which to store items such piesa_a, piesa_b, piesa_c. Then I have to sort items by price.
I have this code so far: http://pastebin.com/nx2FGSfe
The program is incomplete because it does not displays each item in the array.
I got stuck here. But if you display the array's elements when they are outside of it, it works.
SHORT: I have an error on line 143 and I want to solve it.
main.cpp:143:18: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
The code is here:
#include <cstdlib>
#include<iostream>
#include<string.h>
using namespace std;
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
piesa_a()
{
id = 0;
tip = new char[1];
pret = 0;
}
piesa_a(int aidi, char *typ, int pretz)
{
id = aidi;
tip = new char[strlen(typ)+1];
strcpy(tip,typ);
pret = pretz;
}
piesa_a&operator =(piesa_a alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
return *this;
}
virtual void afisare()
{
cout<<"\n Piesa A: "<<id<<" "<<tip<<" "<<pret;
}
};
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
piesa_b():piesa_a(){lungime = 0;bw = 0;}
piesa_b(float lg,bool bl, int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
lungime = lg;
bw = bl;
}
piesa_b&operator =(piesa_b &c)
{
id = c.id;
tip = new char[strlen(c.tip)+1];
strcpy(tip,c.tip);
pret = c.pret;
lungime = c.lungime;
bw = c.bw;
return *this;
}
void afisare()
{
piesa_a::afisare();
cout<<"impreuna cu piesa B: "<<lungime<<" "<<bw<<"\n";
}
};
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
nr = n;
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
piesa_c&operator =(piesa_c &alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
nr = alta.nr;
for(int i=0;i<alta.nr;i++)
buf[i] = alta.buf[i];
}
void afisare()
{
for(int i=0;i<nr;i++)
buf[i].afisare();
}
};
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
What's wrong?
In C++ (and current C), casts are almost always a sign that the programmer didn't know how to use the language as it is supposed to be used. If you need an array of 3 types of data, the cleanest solution is an array of objects of a class that is base to the 3. And if you want to display each item differently, you'll want to overload the << operator, so you just iterate over the array and go << on each item. Sorted by price means that the class includes a price field, and you use the sort from the standard template library, passing a comparison operation that just compares prices.
I've got weird problem. I'm trying to write simple game in C++, but I failed on objects and data types. There's a code:
// C++
// Statki
#include <stdio.h>
#include <time.h>
#include <map>
#include <vector>
#include <string>
#include <list>
#define D true
using namespace std;
void _(char* message){printf("%s\n",message);};
struct relpoint { int x,y; };
struct point { int x,y; };
struct size { int w,h; };
map<const char*, vector<relpoint> > shipshape;
list<char*> shipTypes = {"XS", "S", "M", "L", "XL"};
string alpha="ABCDEFGHIJKLMNOPRSTUVWXYZ";
enum fieldtype { UNKNOWN=-1,EMPTY=0,SHIP=1,HIT=2,MISS=3,};
enum rotation { EAST=0, SOUTH=1, WEST=2, NORTH=3 };
class Ship
{
char* type;
};
class Sea
{
public:
void init(size mapsize) { init( mapsize, EMPTY ); };
void init(size mapsize, fieldtype fill)
{
if(D)printf("Generating sea\n");
vector<fieldtype> v;
seamap.reserve(mapsize.h);
v.reserve(mapsize.w);
for (int y=0; y<mapsize.h; y++)
{
v.clear();
for(int x=0; x<mapsize.w; x++)
{
v.push_back(fill);
}
seamap.push_back(v);
}
view();
};
bool place_ship(Ship ship);
void view()
{
for( vector< vector<fieldtype> >::const_iterator yy = seamap.begin(); yy != seamap.end(); ++yy )
{
for( vector<fieldtype>::const_iterator xx = (*yy).begin(); xx != (*yy).end(); ++xx )
{
if(D)printf("%d ", *xx);
}
if(D)printf("\n");
}
};
private:
vector< vector<fieldtype> > seamap;
};
class Game
{
public:
void initmap(size mapsize)
{
if(D) printf("\nInit %d×%d map\n", mapsize.w, mapsize.h);
(*enemymap).init(mapsize, UNKNOWN);
//(*selfmap).init(mapsize);
};
bool placeship(string type, point position, rotation rotate);
fieldtype shoot(point target);
void viewmap(){(*selfmap).view();};
bool eog();
Sea * enemymap;
Sea * selfmap;
};
class Bot
{
public:
void init(size mapsize)
{
if(D)_("Init Bot");
}
private:
Game * g;
};
class Player
{
public:
Player() { if(D){_("Player fake init");} };
void init(size mapsize)
{
(*g).initmap(mapsize);
};
void viewmap(){(*g).viewmap();};
private:
Game * g;
};
class Router
{
public:
void startgame();
void welcomescreen()
{
printf("\n\n\n\t\t\tShips minigame\n\t\t\t\tby Kris\n\n");
mainmenu();
};
void mainmenu()
{
printf("Menu (type letter):\n\tN: New game\n\tS: Settings\n\tQ: Quit game\n\n > ");
char opt;
opt = toupper(getchar());
size ms;
switch(opt)
{
case 'N':
ms = getmapsize();
(*P1).init(ms);
(*P2).init(ms);
break;
case 'S':
break;
case 'Q':
break;
default:
printf("Invalid option %c", opt);
mainmenu();
}
};
private:
Player * P1;
Bot * P2;
size getmapsize()
{
size ms;
printf("\nSet map size (X Y)\n > ");
scanf("%d %d", &ms.w, &ms.h);
return ms;
};
};
int main () {
vector<relpoint> shp;
shp.reserve(5);
list<char*>::const_iterator tp = shipTypes.begin();
shp.push_back({0,0});
shipshape[*(tp++)] = shp;
shp.push_back({1,0});
shipshape[*(tp++)] = shp;
shp.push_back({2,0});
shipshape[*(tp++)] = shp;
shp.push_back({3,0});
shipshape[*(tp++)] = shp;
shp.push_back({2,1});
shipshape[*tp] = shp;
Router R;
R.welcomescreen();
printf("\n\n");
return 0;
}
It can be compiled, but after line Init 5×5 map program stops with Naruszenie ochrony pamięci (Memory access violation in polish) error. Problem seems to occur at both Sea::init() functions.
I'm compiling it with g++ -std=c++0x -Wno-write-strings ships2.cpp (to prevent warnings) on Ubuntu.
Any idea what's wrong with it?
All the classes contain pointers, but you never seem to initialize the pointers or allocate space for the objects they should point to.
Doing this
(*enemymap).init(mapsize, UNKNOWN);
when enemymap doesn't point anywhere, is an almost sure way to get an access violation.
You are using an uninitialized pointer. You can fix it by instantiating an object here, or in a constructor somewhere else.
Here is an example of instantiating in the initmap call.
void initmap(size mapsize)
{
// Initialize the pointer by instantiating a class
enemymap = new Sea;
if(D) printf("\nInit %d×%d map\n", mapsize.w, mapsize.h);
(*enemymap).init(mapsize, UNKNOWN);
//(*selfmap).init(mapsize);
};
+1 for Bo. But for your own sake:
compile with -g and then then
gdb ./mygame.bin
type 'run'
after setting the map size 5 5 :
Program received signal SIGSEGV, Segmentation fault.
mainmenu (this=<optimized out>) at memacvio.cpp:158
158 (*P1).init(ms);
This should tell you that P1 is probably not a valid poiner.