Avatar billede krismort Nybegynder
17. juni 2004 - 00:17 Der er 4 kommentarer

indkapslede argumenter

Hej
jeg har prøvet at indkapsle x antal argumenter af vilkårlige typer i en ikke template baseret klasse og tænkte på at gøre noget alà:

class Args {
private:
void* lpArgs[MAXARGS];

public:
  enum {
    MAXARGS = 255
  }

  int getNumArgs();
  void* get(int index);
};

void function(const Args& args) {
  int i = args.getNumArgs();
 
  //hvis vi siger der er 1 args men idx 0 som er type long
  long* lpFirst = (long*)args.get(0);
  cout << "arg 1 = " << (long)*lpFirst << endl;
}

Problemet ved denne løsning er bare at man så skal gætte på hvilke type de forskellige argumenter er især da jeg gerne vil have det sådan at man kan bruge klasser som man selv har defineret.

Er der nogen som har en bedre løsning ?
Avatar billede bertelbrander Novice
17. juni 2004 - 00:32 #1
Jeg tvivler lidt på at du finder en pæn måde at løse problemet på, der er for store chancer for at du kommer til at skyde dig selv i foden for mange gange.
Det er bl.a. ikke muligt/ret let at lave noget der er blot lidt type sikker.
Man kan bruge ... til at overføre almindelige type (POD) men de dur ikke til egne typer og der er ingen typecheck.

I praksis tror jeg ikke at der er nogen vej let genvej.

Du kunne prøve at kikke på den sidste løsning her:
http://www.eksperten.dk/spm/495892#rid4573690
Avatar billede segmose Nybegynder
17. juni 2004 - 08:49 #2
Bertel kunne man ikke forestille sig at 
long* lpFirst = (long*)args.get(0);
bliv lavet med dynamic_cast som fx.

long* lpFirst = dynamic_cast<long *>(args.get(0));

evt. kræver det så at alle argumenter er class'er.
Avatar billede bertelbrander Novice
17. juni 2004 - 19:59 #3
Man kunne lave noget i stil med:

#include <vector>
#include <iostream>
#include <string>

class ArgClass
{
public:
  enum ArgType
  {
    IntType,
    DoubleType,
    StringType
  };
private:
  class GenType
  {
  public:
    GenType()
    { }

    GenType(int i)
    {
      Type = ArgClass::IntType;
      Value.i = i;
    }
    GenType(double d)
    {
      Type = ArgClass::DoubleType;
      Value.d = d;
    }

    GenType(std::string s)
    {
      Type = ArgClass::StringType;
      Value.s = s;
    }

    struct
    {
      int i;
      double d;
      std::string s;
    }Value;

    ArgType Type;
  };

  typedef std::vector<GenType> ContainerType;
  ContainerType Container;
  ContainerType::size_type idx;
public:
  ArgClass(GenType a1) : idx(0)
  {
    Container.push_back(a1);
  }
  ArgClass(GenType a1, GenType a2) : idx(0)
  {
    Container.push_back(a1);
    Container.push_back(a2);
  }
  ArgClass(GenType a1, GenType a2, GenType a3) : idx(0)
  {
    Container.push_back(a1);
    Container.push_back(a2);
    Container.push_back(a3);
  }
  ArgClass(GenType a1, GenType a2, GenType a3, GenType a4) : idx(0)
  {
    Container.push_back(a1);
    Container.push_back(a2);
    Container.push_back(a3);
    Container.push_back(a4);
  }

  int GetInt()
  {
    if(idx < Container.size() && Container[idx].Type == IntType)
      return Container[idx++].Value.i;
    return -1; // error
  }

  double GetDouble()
  {
    if(idx < Container.size() && Container[idx].Type == DoubleType)
      return Container[idx++].Value.d;
    return -1; // error
  }

  std::string GetString()
  {
    if(idx < Container.size() && Container[idx].Type == StringType)
      return Container[idx++].Value.s;
    return ""; // error
  }
  ArgType GetType()
  {
    return Container[idx].Type;
  }
  int Num()
  {
    return int(Container.size());
  }
};

class MyClass
{
public:
  void Func(ArgClass Arg)
  {
    for(int i = 0; i < Arg.Num(); i++)
    {
      if(Arg.GetType() == ArgClass::IntType)
        std::cout << "Int: " << Arg.GetInt() << " ";
      else if(Arg.GetType() == ArgClass::DoubleType)
        std::cout << "Double: " << Arg.GetDouble() << " ";
      else
        std::cout << "String: " << Arg.GetString() << " ";
    }
    std::cout << std::endl;
  }
};

int main()
{
  MyClass My;
  My.Func(ArgClass(1));
  My.Func(ArgClass(2, 3.21));
  My.Func(ArgClass(3, 4.321, 5));
  My.Func(ArgClass(3, 4.321, std::string("Whatever"), 5));
}
Avatar billede krismort Nybegynder
18. juni 2004 - 02:24 #4
Det er helt sikkert noget jeg kan bruge til at arbejde viderer med, jeg takker mange gange
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester