Birçok küçük polimorfik sınıfa esnek özellikler (özellikler veya mesajlar veya olaylar olarak kullanım için) C ++


9

Oyunumda gerçekten yararlı olan ancak yavaş yavaş acı çeken iki sınıf var. Mesaj ve Özellik (özellik esasen bir bileşendir).

Her ikisi de bir temel sınıftan türetilir ve statik bir kimlik içerir, böylece sistemler yalnızca istediklerine dikkat edebilir. Çok iyi çalışıyor ... hariç ...

Oyunumu genişletirken sürekli yeni mesaj türleri ve mülk türleri yapıyorum. Her seferinde temelde bir classID ve bir veya iki standart veri türü veya bir işaretçi elde etmek için 2 dosya (hpp ve cpp) ve bir ton demirbaş yazmam gerekiyor.

Oyun oynamayı ve yeni fikirleri test etmeyi gerçek bir angarya haline getirmeye başlıyor. Keşke yeni bir mesaj veya özellik türü oluşturmak istediğimde, sadece şöyle bir şey yazabilmek istiyorum

ShootableProperty:  int gunType, float shotspeed;

ItemCollectedMessage:  int itemType;

üstbilgi ve cpp dosyası oluşturmak yerine, üst sınıf dahil bir yapıcı yazmak vb.

Aklımdaki mantıksal olarak 1 veya 2 satır olanı yapmak için yaklaşık 20-40 satır (korumalar ve her şey dahil).

Bu sorunu çözmek için bir programlama modeli var mı?

Senaryo yazmama ne dersin (ki hiçbir şey bilmiyorum) ... neredeyse aynı sınıfları tanımlamanın bir yolu var mı?


İşte tam olarak bir sınıf neye benziyor:

// Velocity.h

#ifndef VELOCITY_H_
#define VELOCITY_H_

#include "Properties.h"

#include <SFML/System/Vector2.hpp>

namespace LaB
{
namespace P
{

class Velocity: public LaB::Property
{
public:
    static const PropertyID id;

    Velocity(float vx = 0.0, float vy = 0.0)
    : velocity(vx,vy) {}
    Velocity(sf::Vector2f v) : velocity(v) {};

    sf::Vector2f velocity;
};

} /* namespace P */
} /* namespace LaB */
#endif /* LaB::P_VELOCITY_H_ */



// Velocity.cpp

#include "Properties/Velocity.h"

namespace LaB
{
namespace P
{

const PropertyID Velocity::id = Property::registerID();

} /* namespace P */
} /* namespace LaB */

Tüm bunlar sadece bir 2D Vector ve bir 2D vektör beklediğini söyleyen bir kimlik için. (Bazı özelliklerin daha karmaşık unsurları vardır, ancak aynı fikirdir)


3
Şuna bir bakın, size yardımcı olabilir. gameprogrammingpatterns.com/type-object.html

1
Tüm bunlar, şablonun statik başlatma ile değil, yardımcı olabileceği gibi görünüyor. Bu durumda kesinlikle çok daha kolay olabilir, ancak bu kimliklerle ne yapmak istediğiniz ve neden miras kullandığınız hakkında daha fazla bilgi olmadan söylemek zor. Toplumsal kalıtım kullanmak ama hiçbir sanal fonksiyon kesinlikle bir kod kokusu ... Bu çok biçimlilik değil!
ltjax

Onu uygulayan 3. taraf kütüphanesini buldunuz mu?
Boris

Yanıtlar:


1

C ++ güçlüdür, ancak ayrıntılıdır . İstediğiniz şey, hepsi farklı olan çok sayıda küçük polimorfik sınıfsa, evet, bildirmek ve tanımlamak için çok fazla kaynak kodu alacaktır. Bu konuda yapacak bir şey yok, gerçekten.

Şimdi, ltjax'ın dediği gibi, burada yaptığınız şey en azından sağladığınız kod için tam olarak polimorfizm değil . Alt sınıfların belirli uygulamalarını gizleyecek ortak bir arabirim göremiyorum. Sınıf kimliğinin dışında olabilir, ancak bu gerçek sınıf kimliğiyle gereksizdir: adı. Bu sadece bazı veriler içeren bir grup sınıf gibi görünüyor, gerçekten karmaşık bir şey yok.

Ancak bu sorununuzu çözmez: en az kodla çok sayıda ileti ve özellik oluşturmak istiyorsunuz. Daha az kod daha az hata anlamına gelir, dolayısıyla bu akıllıca bir karardır. Ne yazık ki sizin için tek bir çözüm yok. Bu mesajlar ve özelliklerle tam olarak ne yapmak istediğinizi bilmeden ihtiyaçlarınıza en uygun olanı söylemek zor . Öyleyse seçeneklerinizi göstereyim:

  1. C ++ şablonlarını kullanın . Şablonlar derleyicinin sizin için "kod yazmasına" izin vermek için harika bir yoldur. Dil, onları daha iyi desteklemek için geliştikçe C ++ dünyasında giderek daha belirgin hale geliyor (örneğin, artık çok sayıda şablon parametresini kullanabilirsiniz ). Şablonlar aracılığıyla otomatik kod oluşturulmasına adanmış bir disiplin var: şablon meta programlaması . Sorun şu: zor. Böyle bir tekniği kullanmayı planlıyorsanız, programcı olmayanların yeni özellikler ekleyebilmelerini beklemeyin.

  2. Düz eski C makroları kullanın . Eski okul, aşırı kötüye kullanımı kolay ve hataya açık. Onlar da oluşturmak çok basit. Makrolar, önişlemci tarafından gerçekleştirilen yüceltilmiş kopya macunlardır, bu yüzden aslında küçük varyasyonlarla hemen hemen aynı tonlarca şey oluşturmak için oldukça uygundurlar. Ancak makrolar genellikle program tasarımındaki kusurları gizlemek için kullanıldığından, diğer programcıların bunları kullandığınız için sizi sevmesini beklemeyin. Ancak bazen yardımcı olurlar.

  3. Başka bir seçenek, kodu sizin için oluşturmak için harici bir araç kullanmaktır. Daha önceki bir cevapta daha önce bahsedilmişti , bu yüzden genişlemeyeceğim.

  4. Daha az ayrıntılı olan ve sınıfları daha kolay oluşturmanıza olanak tanıyan başka diller de vardır. Dolayısıyla , zaten komut dosyası bağlamalarınız varsa (veya bunlara sahip olmayı planlıyorsanız), bu sınıfları komut dosyasında tanımlamak bir seçenek olabilir. Yine de C ++ 'dan erişmek oldukça karmaşık olacak ve basitleştirilmiş sınıf oluşturma avantajlarının çoğunu kaybedeceksiniz. Yani bu muhtemelen geçerli, oyun mantığınızın çoğunu başka bir dilde yapmayı planlıyorsunuz.

  5. Son olarak, en önemlisi, veri odaklı bir tasarım kullanmayı düşünmelisiniz . Bu "sınıfları", kendi önerdiğinize benzer bir düzen kullanarak basit metin dosyalarında tanımlayabilirsiniz. Bunun için özel bir biçim ve ayrıştırıcı oluşturmanız veya zaten mevcut olan birkaç seçenekten birini kullanmanız gerekir (.ini, XML, JSON ve ne olursa olsun). Daha sonra C ++ tarafında, bu farklı nesne türlerinin toplanmasını destekleyen bir sistem oluşturmanız gerekir. Bu, komut dosyası oluşturma yaklaşımına neredeyse eşdeğerdir (ve muhtemelen daha da fazla çalışma gerektirir), ancak bunu daha hassas bir şekilde ihtiyaçlarınıza göre uyarlayabileceksiniz. Ve bunu yeterince basit yaparsanız, programcı olmayanlar kendi başlarına yeni şeyler yaratabilirler.


0

Size yardımcı olacak bir kod oluşturma aracına ne dersiniz?

örneğin, ileti türünüzü ve üyelerinizi küçük bir metin dosyasında tanımlayabilir ve kod gen aracını ayrıştırıp tüm derleme plakası C ++ dosyalarını bir ön derleme adımı olarak yazabilirsiniz.

ANTLR veya LEX / YACC gibi mevcut çözümler vardır ve mülklerinizin ve mesajlarınızın karmaşıklığına bağlı olarak kendi çözümünüzü almak zor olmayacaktır.


LEX / YACC yaklaşımına sadece bir alternatif, sadece küçük değişiklikler ile çok benzer dosyalar oluşturmak zorunda kaldığımda, basit ve küçük bir python komut dosyası ve etiketleri içeren bir C ++ kod şablonu dosyası kullanıyorum. Python betiği, bu etiketlerin yerini şablonda arar ve bunların yerine oluşturulan öğenin temsili belirteçleri gelir.
victor

0

Google'ın Protokol Tamponları ( http://code.google.com/p/protobuf/ ) hakkında araştırma yapmanızı öneririm . Genel mesajları işlemek için çok akıllıca bir yöntemdir. Sadece bir struct-llike desen özellikleri belirtmeniz gerekir ve bir kod üreteci sınıfları sizin için (Java, C ++ veya C #) tüm işi yapmak. Oluşturulan tüm sınıflar, hem metin tabanlı mesaj başlatma hem de serileştirme için iyi olmalarını sağlayan metin ve ikili ayrıştırıcılara sahiptir.


Mesaj merkezim temel programım - protokol arabelleklerinin herhangi bir büyük yüke maruz kalıp kaldığını biliyor musunuz?
Bryan

API her mesaj için bir Builder sınıfı ve mesajın kendisi için sınıf olduğundan, onlar büyük yükü olduğunu sanmıyorum. Google bunları altyapılarının çekirdeği olarak kullanır. Örneğin, Google App Engine Varlıkları, devam etmeden önce protokol arabelleğine dönüştürülür. Şüpheniz varsa, mevcut uygulamanız ile protokol arabellekleri arasında bir karşılaştırma testi uygulamanızı öneririm. Ek yükün kabul edilebilir olduğunu düşünüyorsanız, bunları kullanın.
dsilva.vinicius
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.