"undefined reference to `operator new(unsigned int)"... Jak stworzyć obiekt w klasie i wywołać konstruktor?

0

Witam,

Ja jestem M.S.Z. i pochodzę z planety Java, jestem nowy w prawdziwym, tzn. obiektowym C++ i mam problem z następującym przykładem

#include "Pin.cpp"





class Logic{
	
	private:
	Pin* pin;
	
	public:
	Logic(){
		
		pin = new Pin('A', 0);
		
	}
	
	
	~Logic(){
		delete pin;
	}
	
	
	void tick(){
		
	//	pin.out();
		
	}
	
};

A teraz wyjaśnienia..

Czego chcę?
Chciałbym stworzyć obiekt typu "Pin" w ciele klasy "Logic", w taki sposób, aby móc wykorzystać metodę tego obiektu w metodzie klasy "Logic".
Stworzenie lokalnej klasy (Pin pin('A', 0);) nie sprawia mi problemu, kompiluje się i działa, jak powinno. Problem tkwi w wykorzystaniu obiektu w całej klasie.

Jaki mam w tym problem?
Problem polega na tym, że kompilując powyższy przykład, gdzie w obrocie mamy "dynamiczną allokację pamięci", kompilator złości się na mnie i mówi:
"undefined reference to `operator new(unsigned int)".

A czego jeszcze chciałbym się dowiedzieć?
Jak jeszcze inaczej mógłbym zrealizować to, czego chcę, są inne sposoby?

Dodatkowe informacje
Pracuję na Atmel Studio 7.0, piszę program na procesor AVR.
Obiektowo programuję od długiego czasu w języku java, tam uproszczono pracę ze wskaźnikami, wystarczy w ciele klasy zdefiniować obiekt np. Pin pin;,
a w konstruktorze pin = new Pin('A', 0); i problem z głowy..

Z góry bardzo dziękuję za wszelkie próby pomocy!

0

Oto zamieszczam bebechy klasy "Pin":


#define uchar unsigned char
#include <avr/io.h>





class Pin{
	
	private:
	
	char port;
	uchar pin;
	
	
	public:
	
	Pin(char port, uchar pin){
		
		this->port = port;
		this->pin = pin;
		
		
		
		
		
		in();
		zero();
		
		
		
		PORTA = 0x03;
		
		
		
		
		
		
		
		
		
		
		
		
		
	}
	
	~Pin(){
		
		
		
	}
	
	
	
	
	
	void out(){
		if(port == 'A'){DDRA |= (1 << pin);}
		if(port == 'B'){DDRB |= (1 << pin);}
		if(port == 'C'){DDRC |= (1 << pin);}
		if(port == 'D'){DDRD |= (1 << pin);}
	}
	
	void in(){
		if(port == 'A'){DDRA &= ~(1 << pin);}
		if(port == 'B'){DDRB &= ~(1 << pin);}
		if(port == 'C'){DDRC &= ~(1 << pin);}
		if(port == 'D'){DDRD &= ~(1 << pin);}
	}
	
	void one(){
		if(port == 'A'){PORTA |= (1 << pin);}
		if(port == 'B'){PORTB |= (1 << pin);}
		if(port == 'C'){PORTC |= (1 << pin);}
		if(port == 'D'){PORTD |= (1 << pin);}
	}
	
	void zero(){
		if(port == 'A'){PORTA &= ~(1 << pin);}
		if(port == 'B'){PORTB &= ~(1 << pin);}
		if(port == 'C'){PORTC &= ~(1 << pin);}
		if(port == 'D'){PORTD &= ~(1 << pin);}
	}
	
	bool getState(){
		if(port == 'A'){if(PINA & (1 << pin)){return true;}else{return false;}}
		if(port == 'B'){if(PINB & (1 << pin)){return true;}else{return false;}}
		if(port == 'C'){if(PINC & (1 << pin)){return true;}else{return false;}}
		if(port == 'D'){if(PIND & (1 << pin)){return true;}else{return false;}}
	}
		
	
};

Na pytanie "Jak to kompilujesz?" z całym szacunkiem, przychodzi mi na myśl tylko jedna odpowiedź.. klikam F7..
Zaraz ściągnę Dev C++ i spróbuje skompilować na nim coś podobnego..

0

Pokombinowałem trochę i wpadłem na pomysł, że można by to zrobić tak:

#include "Pin.cpp"

class Logic{

    private:
    Pin* pin;

    public:
    Logic(){

        Pin pin('A', 0);
		this->pin = &pin;
    }

    ~Logic(){
        
    }

    void tick(){

    //  pin.out();

    }

};

W porządku, to działa, ale czy są jakieś inne sposoby?

0

nie mozesz tak zrobic, bedziesz miec UB (tworzysz lokalna zmienna i przpisujesz do wskaznika. Za konstruktorem ten obiekt nie bedzie juz istnial i bedziesz sie odwolywal do losowej pamieci

skorzystaj ze smart pointerow

0

A właśnie zrobiłem tak, że stworzyłem w ciele klasy wskaźnik "Pin* pin;",
później w konstruktorze stworzyłem obiekt "Pin pin('A', 0);", który jest pełnoprawnym obiektem,
następnie w konstruktorze przypisałem do wskaźnika "pin" adres obiektu "pin", czyli "this->pin = &pin;".

Dzięki temu w metodach klasy "Logic" mogę używać metod obiektu pin w taki sposób; "pin->metoda();"''
To rozwiązanie działa i spisuje się idealnie.

Ciekaw tylko jestem, czy są inne możliwości, czy może to jedyne rozwiązanie..

0

nie wiem ktorego zdania nie rozumiesz

to co robisz jest to UB (undefined behavior)
nie powinienes tak robic. Bo to jest gorszy blad od bledu kompilacji
dziala Ci przez przypadek bo tam w tej pamieci jeszcze nic nie zostalo przypisane. Na innym systemie moze Ci zrobic Syg fault

i istnieje inne rozwiazanie. Poczytaj o smart pointerach z C++11

0

Twierdzisz, że korzystam z resztek oficjalnie nieistniejącego obiektu znajdujących się pod wcześniej zdobytym adresem "&pin"?

0

dokladnie tak jest

0
fasadin napisał(a):

dokladnie tak jest

Ale kicha.. a tak się cieszyłem.. działa, dopóki kompilator czegoś nie wtryni pod "wolny" adres wskaźnika "pin"..

0
fasadin napisał(a):

nie mozesz tak zrobic, bedziesz miec UB (tworzysz lokalna zmienna i przpisujesz do wskaznika. Za konstruktorem ten obiekt nie bedzie juz istnial i bedziesz sie odwolywal do losowej pamieci

skorzystaj ze smart pointerow

Ok, smart pointer.. ale przypomnijmy sobie, że jednym z problemów tego tematu jest fakt, że nie działają raw pointery.. i nie wiadomo, co się z nimi dzieje..

1

To co zrobiłeś to w ogóle jest źle. Zrób tak:

/* pin.h */
#ifndef PIN_H
#define PIN_H

#define uchar unsigned char
#include <avr/io.h>

class Pin {
private:
    char port;
    uchar pin;

public:
    Pin(char port, uchar pin);
    ~Pin();

    void out();
    void in();

    void one();
    void zero();

    bool getState();
};

#endif
/* pin.cpp */
#include "Pin.h"

Pin::Pin(char port, uchar pin)
{
    this->port = port;
    this->pin = pin;

    in();
    zero();

    PORTA = 0x03;
}
   
Pin::~Pin()
{
}

void Pin::out()
{
    if(port == 'A') { DDRA |= (1 << pin); }
    if(port == 'B') { DDRB |= (1 << pin); }
    if(port == 'C') { DDRC |= (1 << pin); }
    if(port == 'D') { DDRD |= (1 << pin); }
}

void Pin::in()
{
    if(port == 'A') { DDRA &= ~(1 << pin); }
    if(port == 'B') { DDRB &= ~(1 << pin); }
    if(port == 'C') { DDRC &= ~(1 << pin); }
    if(port == 'D') { DDRD &= ~(1 << pin); }
}

void Pin::one()
{
    if(port == 'A') { PORTA |= (1 << pin); }
    if(port == 'B') { PORTB |= (1 << pin); }
    if(port == 'C') { PORTC |= (1 << pin); }
    if(port == 'D') { PORTD |= (1 << pin); }
}

void Pin::zero()
{
    if(port == 'A') { PORTA &= ~(1 << pin); }
    if(port == 'B') { PORTB &= ~(1 << pin); }
    if(port == 'C') { PORTC &= ~(1 << pin); }
    if(port == 'D') { PORTD &= ~(1 << pin); }
}

bool Pin::getState()
{
    if(port == 'A') { if(PINA & (1 << pin)) { return true; } else { return false; }}
    if(port == 'B') { if(PINB & (1 << pin)) { return true; } else { return false; }}
    if(port == 'C') { if(PINC & (1 << pin)) { return true; } else { return false; }}
    if(port == 'D') { if(PIND & (1 << pin)) { return true; } else { return false; }}
}

/* Logic.h */
#ifndef LOGIC_H
#define LOGIC_H

#include "Pin.h"

class Logic {
private:
    Pin pin;

public:
    Logic();
    ~Logic();

    void tick();
};

#endif
/* Logic.cpp */
#include "Logic.h"

Logic::Logic() : pin('A', 0)
{
}

Logic::~Logic()
{
}

void Logic::tick()
{
    pin.out();
}

0

Wiesz.. rozumiem, ale ja baaardzo nie chciałem dziedziczyć klasy "Pin"..

1

Dziedziczenie klas tak nie wygląda. Dziedziczenie byś miał gdyby było:

class Logic : public Pin
{
 // ...
};

EDIT: Jeśli myślisz, że to:

Logic::Logic() : pin('A', 0)
{
}

jest dziedziczeniem to nie. Jako, że klasa Pin ma zdefiniowany tylko konstruktor z argumentami to gdzieś go musisz wywołać tworząc obiekt. Jedynym sposobem takiego wywołania dla obiektu w klasie jest lista inicjalizacyjna.

0

A zatem bardzo dziękuję wszystkim i w szczególności mwl4 za rozwiązanie problemu przy pomocy listy inicjalizacyjnej, dzięki której możliwe jest wywołanie konstruktora dla obiektu stworzonego w ciele klasy. Problem został po części rozwiązany, jedyne, czego jeszcze nie rozumiem, to.. dlaczego raw pointer nie działa.. może się to jeszcze wyjaśni, w każdym razie jeszcze raz dziękuję.

0

Bo avr-gcc nie zawiera biblioteki standardowej C++.
RTFM. http://www.atmel.com/webdoc/avrlibcreferencemanual/FAQ_1faq_cplusplus.html :)
Jak sobie operator new napiszesz to będziesz go mieć.
Ogólnie do nauki embedded i C++ (C++, nie C, podkreślam) polecałbym inną architekturę, Cortex M0/M3/M4 np. są o wiele lepszym wyborem.

EDIT: tak poza tematem: taka implementacja klasy 'Pin' imho jest nie do końca dobra. Zamierzasz w istniejącym obiekcie zmieniać porty na A, B, C D itd.? Zakładam, że nie. Czy nie lepiej użyć wtedy referencji na dany rejestr zamiast tej drabinki ifów?

1 użytkowników online, w tym zalogowanych: 0, gości: 1