unique_ptr

0

Hej!
Nawet nie wiem jak nazwać problem, z którym borykam się już od kilku godzin i nie potrafię rozwiązać, najdziwniejsze, że nie wiem z czego on wynika. Skupmy się na dwóch klasach jedna zwraca nam wskaźnik na obiekt danej klasy a w drugiej chciałabym na podstawie tych zwracanych obiektów tworzyć drzewo, ponieważ te dwie klasy nie dziedziczą jedna po drugiej do jednej z nich-> AbstractExpression chciałabym dodać obiekt drugiej ->Parser aby móc korzystać z funkcji która zwraca mi te obiekty niestety nie jestem w stanie dodać nawet pliku nagłówkowego ponieważ sypie się ok 100 błędów:

#pragma once
#include<memory>
#include<vector>
#include<utility>
#include "Parser.h" //dodany plik nagłówkowy
class AbstractExpression
{
protected:
    std::unique_ptr<AbstractExpression> startSymbol;
    std::unique_ptr<AbstractExpression> leftNode;
    std::unique_ptr<AbstractExpression> rightNode;
public:
    AbstractExpression();
    /*void setRoot(AbstractExpression*& root);
    void setLeftNode(AbstractExpression*& leftNode);
    void setRightNode(AbstractExpression*& rightNode);*/
    AbstractExpression& operator=(AbstractExpression&& expr);
    std::unique_ptr<AbstractExpression> getRoot();
    std::unique_ptr<AbstractExpression> getLeftNode();
    std::unique_ptr<AbstractExpression> getRightNode();
    virtual void buildAST(std::unique_ptr<AbstractExpression> expr);
    virtual ~AbstractExpression();
};

#pragma once
#include"Lexer.h"
#include"Token.h"
#include<stack>
#include"AbstractExpression.h"
#include"Number.h"
#include"Operator.h"
#include<variant>
#include"Addition.h"
#include"Lexer.h"
#include<memory>
class Parser
{
    Lexer lexer;
    std::stack<token>  abstractStackMachine;
    token  currentToken;
public:
    Parser();
    std::unique_ptr<AbstractExpression> parse();
    ~Parser();
};

w tym coś takiego:
'default_delete': unspecialized class template can't be used as a template argument for template parameter '_Dx', expected a real type
'std::unique_ptr': 'AbstractExpression' is not a valid template type argument for parameter '_Ty' pro
S'std::unique_ptr': use of class template requires template argument list
'default_delete': symbol is neither a class template nor a function template

Klasa Number jest szablonem.
Byłabym bardzo wdzięczna za jakakolwiek pomoc, dopóki nie dodam nagłówkowego pliku Parser do AbstractExpression wszystko działa i obiekty są poprawnie zwracane. Dodanie :AbstractExpression& operator=(const AbstractExpression& expr)=delete i AbstractExpression(const AbstractExpression&expr)=delete nie pomaga. Żaden obiekt klasy Parser nie jest stworzony więc dlaczego już przy dodaniu samego pliku nagłówkowego się wywraca i jak mogę korzystać w klasie AbstractExpression z tych zwracanych przez Parser wskaźników na obiekty?
Z góry bardzo dziękuję za jakiekolwiek podpowiedzi!

1

Odpowiedź to: użyj forward declaration.

// AbstractExpression.h
#pragma once

#include <memory>
#include <vector>
#include <utility>

class AbstractExpression
{
protected:
    std::unique_ptr<AbstractExpression> startSymbol;
    std::unique_ptr<AbstractExpression> leftNode;
    std::unique_ptr<AbstractExpression> rightNode;
public:
    AbstractExpression();
    /*void setRoot(AbstractExpression*& root);
    void setLeftNode(AbstractExpression*& leftNode);
    void setRightNode(AbstractExpression*& rightNode);*/
    AbstractExpression& operator=(AbstractExpression&& expr);
    std::unique_ptr<AbstractExpression> getRoot();
    std::unique_ptr<AbstractExpression> getLeftNode();
    std::unique_ptr<AbstractExpression> getRightNode();
    virtual void buildAST(std::unique_ptr<AbstractExpression> expr);
    virtual ~AbstractExpression();
};
// AbstractExpression.cpp
#include "pch.h" // precompiled headers - dobrze jest to zdefiniować w kompilatorze, jeśli nie masz to możesz usunąć tę linię
#include "AbstractExpression.h"

AbstractExpression::AbstractExpression()
{
}

// implementacje innych metod
// Parser.h
#pragma once

#include "Lexer.h"
#include "Token.h"

#include <stack>
#include <variant>
#include <memory>

class AbstractExpression;

class Parser
{
    Lexer lexer;
    std::stack<token>  abstractStackMachine;
    token  currentToken;
public:
    Parser();
    std::unique_ptr<AbstractExpression> parse();
    ~Parser();
};
// Parser.cpp
#include "pch.h" // precompiled headers - dobrze jest to zdefiniować w kompilatorze, jeśli nie masz to możesz usunąć tę linię
#include "Parser.h"

#include "AbstractExpression.h"

std::unique_ptr<AbstractExpression> Parser::parse()
{
// implementacja metody
}
1

Po co ci

#include "Parser.h"

Przy definicji klasy AbstractExpression?
Przecież symbol Parser nie jest tam wykorzystywany.
A co do forward declaration to jest dobra praktyka, posta instrukcja: https://4programmers.net/Forum/C_i_C++/137960-C++_Unikanie_include_w_plikach_naglowkowych?p=513176#id513176

0

Już mówię jest mi to potrzebne ponieważ chciałabym korzystać w metodzie buildAST z metody Parsera czyli parse(); Dodalam do AbstractExpression.cpp Parser.h i mogę stricte w metodzie build korzystać z obiektu Parsera jednakże jeżeli chialabym stworzyć prywatne pole Parser w klasie AbstractExpression niestety nie jestem w stanie. Przy dodaniu w Parser.h, class AbstractExpression i w Parser.cpp AbstractExpression.h niestety również nie działa.

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