getter i setter i problem z inline w pliku cpp

0

Mam prostą klasę i typ wyliczeniowy. Klasa jest pozbawiona metod by nie zaciemniać problemu. W niej jeden getter i setter. Gettery i settery są to (zazwyczaj) proste metody o minimalnej ilości kodu więc warto je definiować jako inline. Jeśli klasę zdefiniuję całą w pliku .h to wszystko jest dobrze. Jeśli oddzielę definicje od deklaracji i przeniosę je do pliku .cpp ale bez słowa inline to też jest dobrze (w sensie kompilacja i linkowanie bez ostrzeżeń i błędów). Ale jeśli chciałbym oddzielić deklaracje od definicji i dodatkowo oznaczyć setter i getter jako inline czyli jeśli robię to tak jak poniżej…
golccell.h

#ifndef GOLC_CELL_H
#define GOLC_CELL_H

enum Direction { N, E, S, W, EMPTY };

class Cell {
public:
    Direction getDirection() const;
    
    void setDirection(Direction direction);

private:
    Direction direction = EMPTY;
};

#endif

golccell.cpp

#include "golccell.h"

inline Direction Cell::getDirection() const {
    return direction;
}

inline void Cell::setDirection(Direction direction) {
    Cell::direction = direction;
}

to pojawia się błąd przy linkowaniu o następującej treści:

/tmp/ccq8WcAE.o:main.cpp:(.text+0x21): undefined reference to `Cell::setDirection(Direction)'
/tmp/ccq8WcAE.o:main.cpp:(.text+0x21): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Cell::setDirection(Direction)'
/tmp/ccq8WcAE.o:main.cpp:(.text+0x2d): undefined reference to `Cell::getDirection() const'
/tmp/ccq8WcAE.o:main.cpp:(.text+0x2d): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Cell::getDirection() const'
collect2: error: ld returned 1 exit status

Mogę te definicje dać w pliku .h ale jednak zależy mi na tym by oddzielić definicje od deklaracji tym bardziej, że sama klasa jest dużo bardziej złożona i nie chciałbym mieć część definicji tu, a pozostałą część tu.
O co chodzi z tym "niezdefiniowanym symbolem" i jak umieścić definicje tych dwóch metod w pliku .cpp tak, żeby dały się oznaczyć jako inline?

PS. Wiem, że inline jest tylko sugestią i nie mam pewności, że kompilator rozwinie ich ciało włączając bezpośrednio w kod je wywołujący (jak i w druga stronę). Ale chciałbym to jednak ładnie pogrupować.

PS2.
main.cpp

#include <iostream>
#include "golccell.h"

int main() {
    Cell cell;
    
    cell.setDirection(Direction::N);
    std::cout << cell.getDirection() << std::endl;
    
    return 0;
}

Kompiluję jako: g++ -std=c++11 main.cpp golccell.cpp

1

Krótka odpowiedź: nie możesz. Kompilator potrzebuje definicji funkcji inline za każdym razem gdy widzi jej użycie. Przeniesienie tego do pliku cpp powoduje, że w miejscu użycia ma dostęp jedynie do deklaracji w nagłówku.
A tak filozoficznie to skoro funkcja jest na tyle krótka i banalna, że powinna być inline to definicja powinna być od razu w środku klasy i tyle.

0

"Member functions defined in-class are inline by default." https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rf-inline

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