1

I'm currently working on a C++ header for encoding and decoding text. To be exact: UTF-8, UTF-16, UCS-2 and UTF-32. But I've come to a point where my C++ knowledge won't get me any further:

I'd like to use an abstract class for decoding and encoding, while creating base classes for each codec. Then, if using any function related to encoding or decoding, the dev should be able to just pass a custom data type to the function.

The problem is that I don't have any clue how to actually do this. After all, you can't pass a static class as a parameter. But I don't want to hardcode anything either; the dev should also be able to add any codec without much trouble and without modifying my header.

Also, it should be as easy as possible. The code would look something like this:

namespace Encoding {

  class Encoder {
  public:
    virtual std::string Encode(std::string sOriginal) = 0;
  };

  // Derived classes like UTF8 and UCS2 here

}

void OutputEncoded(std::string s, Encoder enc) {
  std::cout << enc.Encode(s);
}


int main() {
  OutputEncoded("Hellö Wörld!", Encoding::UTF8);
}

Any idea how to do this? Maybe a way without creating an object but with just the static methods? Or do I have to use an object with a pointer?

  • 3
    what is a static class? – 463035818_is_not_an_ai Apr 23 '20 at 15:20
  • are you coming from c# maybe? C++ does not have "static classes", the only thing I found was [this question](https://stackoverflow.com/questions/9321/how-do-you-create-a-static-class-in-c) where from OPs code it was possible to know what they meant. Maybe if you include some code this is also possible here – 463035818_is_not_an_ai Apr 23 '20 at 15:23
  • 1
    Please include a [mcve] of the code you would like to write, not matter how broken, it will help to clarify – 463035818_is_not_an_ai Apr 23 '20 at 15:25
  • is it possible that you use "static" to mean "not abstract" ? – 463035818_is_not_an_ai Apr 23 '20 at 15:28
  • I will ignore the use of the word `static` here because it does not help. Given that, I would suggest you look up the abstract factory pattern. That sounds close to what you want. – andre Apr 23 '20 at 15:32
  • @idclev463035818 Now I'm confused What does it do when I write "static class XYZ {};"? Because this does compile and run. What I mean by "static" is that you can't create any objects of it. Because, why would it make sense to create an object of an en-/decoder? There are just static methods inside, after all. –  Apr 23 '20 at 15:38
  • `static class XYZ {};` is a syntax error ("a storage class can only be specified for objects and functions"). There is no name for classes with only static methods in c++, because there is little use for them in c++, free functions in a namespace are usually prefered. Also having only static methods does not prevent you from creating an instance – 463035818_is_not_an_ai Apr 23 '20 at 15:43
  • btw thats why I asked you to show some code, really anything helps to avoid such misunderstanding. Now I am curious how you can get `static class XYZ {};` get to compile without an error – 463035818_is_not_an_ai Apr 23 '20 at 15:45
  • Oh, alright then. (But still; at least in VS, it doesn't throw any errors) I found an answer myself, gonna edit the question now to not contain the word "static" anymore and will answer it myself. Still, thank you idclev463035818 and andre. –  Apr 23 '20 at 15:48
  • Here's my code: https://pastebin.com/2JNURgR6 –  Apr 23 '20 at 15:55
  • 2
    Comment are not the best place to write code. (if relevant) edit your question (or answer), they have better formatting. – Jarod42 Apr 23 '20 at 15:58
  • I see. The more you know ;) It's better now, I guess. –  Apr 23 '20 at 16:00
  • 1
    There are some [online IDEs](https://arnemertz.github.io/online-compilers/) more appropriate than pastebin. – Jarod42 Apr 23 '20 at 16:03

2 Answers2

1

I found a way myself. Pretty simple, actually.

class Base {
public:
  virtual void DoSomething(void) = 0;
};

class Derived : public Base {
  void DoSomething(void) {
    std::cout << "Test";
  }
} DerivedTest;

Base* const DerivedTestPtr = &DerivedTest;



void Test(Base* b) {
  b->DoSomething();
}



int main() {
  Test(DerivedTestPtr);
}
  • 1
    You might even avoid global variable; `int main() { Derived d; Test(&d); }` Passing by reference is more appropriate than by pointer as `nullptr` is wrong input. – Jarod42 Apr 23 '20 at 15:56
  • you could also clarify your question, because without the code from the link in your comment it isnt quite clear what question this is answering. I would add the code and the error message, then this would make a good answer i guess – 463035818_is_not_an_ai Apr 23 '20 at 16:01
  • @Jarod42 The point is to make it as easy as possible. A line of code should look like "EncodeString("Hello wörld", UTF8);" –  Apr 23 '20 at 16:07
  • @RobinLe but if your original code was fine already then what was the question? – 463035818_is_not_an_ai Apr 23 '20 at 16:11
  • How to do it PROPERLY. It looked way too quick and dirty to me. I thought there would be a better way, maybe even more efficient. –  Apr 23 '20 at 16:13
  • kudos for making an serious attempt to fix the quesiton +1 – 463035818_is_not_an_ai Apr 23 '20 at 16:17
  • @idclev463035818 I'm sorry for being way too vague. I'm still kind of a total beginner both at C++ and StackOverflow (even though I've written code in C++ for more than 1.5 years). –  Apr 23 '20 at 16:19
1

Possible alternative to abstract class is template:

namespace Encoding {

  class UTF8 {
  public:
    static std::string Encode(std::string sOriginal);
  };
  class UCS2 {
  public:
    static std::string Encode(std::string sOriginal);
  };

}

template <typename Encoder>
void OutputEncoded(const std::string& s) {
  std::cout << Encoder::Encode(s);
}

int main()
{
  OutputEncoded<Encoding::UTF8>("Hellö Wörld!");
}

Classes UTF8 and UCS2 should respect compatible/same interface, without the enforcement provided by abstract class and virtual method.

C++20 concept might help to enforce correct usage. Before SFINAE might be used, but more verbose.

Jarod42
  • 203,559
  • 14
  • 181
  • 302