User 13204940 Ответов: 1

Наследование C++/переопределение методов базового класса


Привет,

Обычно класс AFuelTank наследуется от AActor. AFuelTank содержит этот метод
virtual void BeginPlay() override;
поскольку он может переопределить метод BeginPlay() AActor.

Теперь я представляю класс в середине, поскольку AFuelTank разделяет определенные свойства с другими реализациями AActor. Я пытаюсь, чтобы AFuelTank унаследовал от ASpawnable, а это от AActor.

Чтобы пояснить, вот пример структуры, происходящей здесь.

AFuelTank
AWaterTank - все наследуют от ASpawnable
APlayer

Аоне
Адва - все наследуют ряд
Атри

ASpawnable и ANumber затем наследуются от базового класса AActor, и каждый из них имеет
virtual void Init()
для AFuelTank, AWaterTank и т. д., чтобы переопределить.

Я получаю целый ряд ошибок, касающихся этого наследования и переопределения.

Вот как следует использовать каждый метод:

Когда вызывается AFuelTank::BeginPlay (), он должен вызвать BeginPlay ASpawnable(), и это вызовет BeginPlay AActor();

Когда AFuelTank::init() вызывается, она должна назвать конкретную реализацию AFuelTank в методе init(), в виртуальную пустоту методе init() присутствует в ASpawnable готов быть переопределен.

Не могли бы вы помочь мне выяснить правильные комбинации "виртуального" и "переопределения" для каждого из этих методов?

Это дерево наследования здесь[^]

Редактировать:
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ASpawnable.generated.h"

UCLASS()
class NOCTURNALSYNERGY_API AASpawnable : public AActor
{
	GENERATED_BODY()
	
public:	
	//virtual void Init();

protected:
	//virtual void BeginPlay();

};
#include "ASpawnable.h"

//void AASpawnable::Init()
//{
//
//}
//
//void AASpawnable::BeginPlay()
//{
//	Super::BeginPlay();
//}
#pragma once

#include "../../Helpers/DebugHelper.h"
#include "../../Helpers/MathsHelper.h"
#include "ContainerAttributes.h"
#include "../ASpawnable.h"

#include "CoreMinimal.h"
#include "FuelTank.generated.h"

UCLASS()
class NOCTURNALSYNERGY_API AFuelTank : public ASpawnable
{
	GENERATED_BODY()

public:
	AFuelTank();
	//virtual void Init() override;
	
	// returns the tank's level
	int GetLevel();

	// returns the tank's capacity
	int GetCapacity();

	// returns the amount of fuel in the tank
	int GetFuel();

	// returns the tank's max health
	int GetMaxHealth();

	// returns the tank's health
	int GetHealth();

	// upgrades the tank to the next level
	void Upgrade();

	// decreases fuel amount if possible, returns amount removed
	int DepleteFuel(int amount);

	// increases fuel amount if possible, returns amount added
	int AddFuel(int amount);

protected:
	//virtual void BeginPlay() override;

private:
	ContainerAttributes containerAttributes;
	const int maxLevel = 4;
	
};
#include "FuelTank.h"

AFuelTank::AFuelTank()
{

}

//void AFuelTank::Init()
//{

//}

//void AFuelTank::BeginPlay()
//{
//	Super::BeginPlay();
//}

int AFuelTank::GetLevel()
{
	return containerAttributes.GetValue("level");
}

int AFuelTank::GetCapacity()
{
	return containerAttributes.GetValue("capacity");
}

int AFuelTank::GetFuel()
{
	return containerAttributes.GetValue("amount");
}

int AFuelTank::GetMaxHealth()
{
	return containerAttributes.GetValue("maxHealth");
}

int AFuelTank::GetHealth()
{
	return containerAttributes.GetValue("health");
}

void AFuelTank::Upgrade()
{
	containerAttributes.SetValue("level", GetLevel() + 1);
}

int AFuelTank::DepleteFuel(int amount)
{
	int fuel = GetFuel();
	int toRemove = MathsHelper::Min(amount, fuel);

	containerAttributes.SetValue("amount", fuel - toRemove);
	return toRemove;
}

int AFuelTank::AddFuel(int amount)
{
	int fuel = GetFuel();
	int capacity = GetCapacity();
	int toAdd = MathsHelper::Min(amount, capacity - fuel);

	containerAttributes.SetValue("amount", fuel + amount);
	return amount;
}


Ошибки:

Топливный бак.h:
class NOCTURNALSYNERGY_API AFuelTank : public ASpawnable

Ошибка на ASpawnable - "не имя класса или структуры"

Дополнительная ошибка EXEC: "не удалось найти родительский тип для 'FuelTank' с именем 'ASpawnable' в текущем модуле или любом другом модуле, проанализированном до сих пор."

Что я уже пробовал:

-------------------------------------------------------------------------------

Richard MacCutchan

"Я получаю целый ряд ошибок "
Затем, пожалуйста, покажите код, который вызывает ошибку, и фактические сообщения.

[no name]

С таким огромным проектом intellisense работает ужасно медленно и часто уведомляет об ошибках, которые затем исчезают без вмешательства, поэтому я не могу ему доверять. Я отредактирую вопрос со всем кодом.

[no name]

Опять же, жалкий рейтинг ничего не дает. Это почти так же, как если бы не знать, что решение достойно 1 звезды. Это идея задавать вопрос, на который вы не знаете ответа. Я объяснил это так подробно, как только мог, и не знаю, чего еще от меня ждут. Опять же, ясно, что это делается для того, чтобы другие чувствовали себя лучше о своих печальных личностях.

Richard MacCutchan

Я подозреваю, что люди понижают ваш голос, потому что ваш вопрос неполон. Когда вы добавляете комментарий, такой как "я получаю ошибки" или "это не работает", у нас нет возможности угадать, в чем проблема, поэтому чтение сообщения чрезвычайно расстраивает. И это не личное, это одна из самых распространенных проблем с вопросами, размещенными здесь. Если вам нужна помощь, то вам действительно нужно предоставить максимальное количество релевантной информации.

[no name]

И это проблема судить, не будучи образованным в данной ситуации. Я не мог доверять информации, которую мне дали, поэтому я сделал все, что мог, чтобы предоставить адекватную информацию.

Причина, по которой эти проблемы могут возникнуть, может быть только из-за неправильных определений методов. Из дерева наследования и моих описаний любой мог бы ответить правильными определениями методов, затем я мог бы исправить их в своем решении, и проблемы были бы решены. Я не делаю ничего сложного с моим проектом, просто создаю базовые файлы, поэтому не будет никаких странных ошибок, не связанных с конкретным сценарием, который я описываю.

Независимо от того, является ли плохой рейтинг личным или нет, что именно является намерением? Это не заставит меня волшебным образом дать больше информации. Совершенно ясно, что люди делают это, чтобы понизить репутацию других и заставить их казаться выше, что бессмысленно с кем-то вроде меня, кто не может меньше заботиться о репутации и использует этот форум исключительно тогда, когда все другие методы отладки потерпели неудачу, в качестве последнего средства.

Richard MacCutchan

Но проблема остается в том, что мы не можем угадать, что у вас на уме. И если вы не можете доверять информации, которую видите, почему вы сообщаете об этом как о проблеме? Вам нужно посмотреть на это с точки зрения кучки незнакомцев, которые понятия не имеют, что вы делаете, какова может быть окружающая среда и т. д. И многие из этих незнакомцев не имеют английского языка в качестве первого языка, поэтому ясность еще более важна.

[no name]

Боюсь, что здесь не так уж много места для подробного объяснения, если вы должны принять во внимание упрощение вещей для тех, кто не говорит свободно по-английски на англоязычном форуме.

Richard MacCutchan

Я не сказал, чтобы это было просто, но сделать это ясно.

[no name]

Я надеялся, что прилагаемое изображение прояснится визуально.

Richard MacCutchan

Многие люди будут игнорировать ссылки как потенциально опасные; у нас есть довольно большая проблема со спамерами на сайте. От вас ожидается, что вы предоставите всю соответствующую информацию в самом вопросе.

[no name]

Я понимаю это, но это довольно хорошо объясненный вопрос, чтобы иметь в нем случайное опасное звено. Я бы ожидал, что очень спамовое сообщение будет сопровождаться такими ссылками

Richard MacCutchan

Это так же возможно, но многие люди все еще игнорируют ссылки как само собой разумеющееся.

1 Ответов

Рейтинг:
1

Richard MacCutchan

class NOCTURNALSYNERGY_API AASpawnable : public AActor

class NOCTURNALSYNERGY_API AFuelTank : public ASpawnable

Простая орфографическая ошибка.


[no name]

Ах, я создал файл с именем ASpawnable, тогда как он должен быть Spawnable. Спасибо!

[no name]

Теперь я исправил это и попытался снова включить свои методы, я получаю другие ошибки.

"ASpawnable: не удается создать экземпляр абстрактного класса"

(уже сделано двигателем) AActor::BeginPlay() доступен для переопределения при необходимости.

Это то, что я ищу:
• ASpawnable::BeginPlay() доступен для переопределения при необходимости.
• ASpawnable::Init() должен быть переопределен производным классом

Методы в топливном баке:
• AFuelTank::BeginPlay() // не обязательно существовать, но может
• AFuelTank::Init() // должен существовать

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Spawnable.generated.h"

UCLASS()
class NOCTURNALSYNERGY_API ASpawnable : public AActor
{
	GENERATED_BODY()
	
protected:
	virtual void Init() = 0;
	virtual void BeginPlay() override;

};
#include "Spawnable.h"

void ASpawnable::BeginPlay()
{
	Super::BeginPlay();
}
#pragma once

#include "../../Helpers/DebugHelper.h"
#include "../../Helpers/MathsHelper.h"
#include "ContainerAttributes.h"
#include "../Spawnable.h"

#include "CoreMinimal.h"
#include "FuelTank.generated.h"

UCLASS()
class NOCTURNALSYNERGY_API AFuelTank : public ASpawnable
{
	GENERATED_BODY()

public:
	AFuelTank();

protected:
	virtual void BeginPlay() override;
	virtual void Init() override;
	
};
#include "FuelTank.h"

AFuelTank::AFuelTank()
{

}

void AFuelTank::BeginPlay()
{
	Super::BeginPlay();
}

void AFuelTank::Init()
{
	// do something
}

Richard MacCutchan

Декларация
virtual void Init() = 0;
делает ASpawnable абстрактным классом.