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

Odpowiedz Nowy wątek
2017-08-07 09:36
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!

edytowany 3x, ostatnio: M.S.Z., 2017-08-07 10:18
Pokaż klasę Pin i pokaż jak kompilujesz. - szweszwe 2017-08-07 09:51

Pozostało 580 znaków

2017-08-07 10:00
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..

edytowany 1x, ostatnio: M.S.Z., 2017-08-07 10:03

Pozostało 580 znaków

2017-08-07 10:23
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?

edytowany 1x, ostatnio: M.S.Z., 2017-08-07 10:24
Dlaczego plik nagłówkowy ma rozszerzenie .cpp? Dodaj include guardy. - _0x666_ 2017-08-07 11:25

Pozostało 580 znaków

2017-08-07 10:27
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

Pozostało 580 znaków

2017-08-07 11:06
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..

edytowany 1x, ostatnio: M.S.Z., 2017-08-07 11:07

Pozostało 580 znaków

2017-08-07 11:19
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

edytowany 1x, ostatnio: fasadin, 2017-08-07 11:19

Pozostało 580 znaków

2017-08-07 11:23
0

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

Pozostało 580 znaków

2017-08-07 11:24
0

dokladnie tak jest

Pozostało 580 znaków

2017-08-07 11:26
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"..

Pozostało 580 znaków

2017-08-07 11:32
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..

doczytaj czym jest smart pointer. Raw pointerow sie nie uzywa w C++ od paru lat - fasadin 2017-08-07 11:36

Pozostało 580 znaków

2017-08-07 11:35

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();
}

Asm/C/C++
edytowany 2x, ostatnio: mwl4, 2017-08-07 11:37
dlaczego logika w konstruktorze? - fasadin 2017-08-07 11:36
Bardziej chodziło o to, że on sobie includuje .cpp w swoim kodzie (nie ma plików .h). A sam wygląd kodu to już inna sprawa. - mwl4 2017-08-07 11:38
@M.S.Z.: Twoj komentarz nie ma zadnego sensu - fasadin 2017-08-07 11:46
@M.S.Z.: To nie jest dziedziczenie (zobacz post na drugiej stronie). A jeśli chodzi o tysiące plków .h -> trudno. Nie da się tego inaczej porządnie zrobić (chyba, że będziesz implementował metody od razu w plikach .h, tylko, że możesz się pewnego dnia zdziwić dlaczego się kod nie kompiluje (ze względu na zagnieżdżenie includów) - mwl4 2017-08-07 11:46

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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