51
#include "Includes.h"


enum BlowfishAlgorithm
    {
        ECB,
        CBC,
        CFB64,
        OFB64,
    };

class Blowfish
{
public:
    struct bf_key_st
    {
        unsigned long P[18];
        unsigned long S[1024];
    };
    Blowfish(BlowfishAlgorithm algorithm);
    void Dispose();
    void SetKey(unsigned char data[]);
    unsigned char Encrypt(unsigned char buffer[]);
    unsigned char Decrypt(unsigned char buffer[]);
    char EncryptIV();
    char DecryptIV();
private:
    BlowfishAlgorithm _algorithm;
    unsigned char _encryptIv[200];
    unsigned char _decryptIv[200];
    int _encryptNum;
    int _decryptNum;
};

class GameCryptography
{
public:
    Blowfish _blowfish;
    GameCryptography(unsigned char key[]);
    void Decrypt(unsigned char packet[]);
    void Encrypt(unsigned char packet[]);
    Blowfish Blowfish;
    void SetKey(unsigned char k[]);
    void SetIvs(unsigned char i1[],unsigned char i2[]);
};




GameCryptography::GameCryptography(unsigned char key[])
{
}

Error:IntelliSense: no default constructor exists for class "Blowfish" ???!

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Abanoub
  • 3,623
  • 16
  • 66
  • 104
  • Please don't delete your entire question. Leave it in place. – greyfade Feb 12 '11 at 23:23
  • 1
    Not having a default constructor is no problem, as long as you don't use one. Always specifying an argument at construction is ok, when there is no obvious default argument. – Bo Persson Feb 13 '11 at 14:52
  • The question has already been asked a long time ago, still for completion, in order to force the compiler to generate a default constructor one can use: ` { public: () = default; }` with default forcing a default constructor for the class. In this case: `class Blowfish { Blowfish() = default; }` – Max Kuchenkiller Nov 07 '19 at 11:52

5 Answers5

74

If you define a class without any constructor, the compiler will synthesize a constructor for you (and that will be a default constructor -- i.e., one that doesn't require any arguments). If, however, you do define a constructor, (even if it does take one or more arguments) the compiler will not synthesize a constructor for you -- at that point, you've taken responsibility for constructing objects of that class, so the compiler "steps back", so to speak, and leaves that job to you.

You have two choices. You need to either provide a default constructor, or you need to supply the correct parameter when you define an object. For example, you could change your constructor to look something like:

Blowfish(BlowfishAlgorithm algorithm = CBC);

...so the ctor could be invoked without (explicitly) specifying an algorithm (in which case it would use CBC as the algorithm).

The other alternative would be to explicitly specify the algorithm when you define a Blowfish object:

class GameCryptography { 
    Blowfish blowfish_;
public:
    GameCryptography() : blowfish_(ECB) {}
    // ...
};

In C++ 11 (or later) you have one more option available. You can define your constructor that takes an argument, but then tell the compiler to generate the constructor it would have if you didn't define one:

class GameCryptography { 
public:

    // define our ctor that takes an argument
    GameCryptography(BlofishAlgorithm); 

    // Tell the compiler to do what it would have if we didn't define a ctor:
    GameCryptography() = default;
};

As a final note, I think it's worth mentioning that ECB, CBC, CFB, etc., are modes of operation, not really encryption algorithms themselves. Calling them algorithms won't bother the compiler, but is unreasonably likely to cause a problem for others reading the code.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • What if I'm trying to initialize an array of Blowfish objects? i.e: Blowfish blowfish_[] ... how do I use ctor for that? – neid Sep 30 '14 at 19:26
  • 3
    @nagheid: Objects in such an array are always constructed with default constructors. By far the easiest workaround is `std::vector`, though you can do it yourself with `std::aligned_storage` and placement new – Mooing Duck Dec 05 '14 at 18:14
  • GameCryptography only cares that Blowfish doesn't have a default constructor because of the declaration Blowfish \_blowfish; You don't need to have default constructors. Would another solution simply be to declare Blowfish \_blowfish = Blowfish(BlowfishAlgorithm);? – Ben Alan Oct 27 '21 at 17:16
  • @BenAlan: Yes, something on that order would work as well (e.g., also `Blowfish blowfish_{ECB};`) – Jerry Coffin Oct 27 '21 at 17:41
7

Because you have this:

Blowfish(BlowfishAlgorithm algorithm);

It's not a default constructor. The default constructor is one which takes no parameters. i.e.

Blowfish();
Dave
  • 3,438
  • 20
  • 13
5

A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values.

Mārtiņš Briedis
  • 17,396
  • 5
  • 54
  • 76
5

You declared the constructor Blowfish as this:

Blowfish(BlowfishAlgorithm algorithm);

So this line cannot exist (without further initialization later):

Blowfish _blowfish;

Since you passed no parameter. It does not understand how to handle a parameter-less declaration of object Blowfish - you need to create another constructor for that.

Note: If you define user-provided constructor(s), the default constructor will disappear.

user16217248
  • 3,119
  • 19
  • 19
  • 37
RageD
  • 6,693
  • 4
  • 30
  • 37
1

This is a typical human error. Intelisense is asking for that for one reason, you are creating an object without parameters in the stack:

public:
Blowfish _blowfish;

That declaration requires a default constructor. One option to correct this is to create the object with new.

Blowfish myBlowfish = new Blowfish(algorithm);

The second options is to create default constructor as requested.

  • `Blowfish myBlowfish = new Blowfish(algorithm);` will not compile since `myBlowfish` is not a pointer. You would need `Blowfish *myBlowfish = new Blowfish(algorithm);` instead (and don't forget to `delete myBlowfish;` when you are done using it). Otherwise, just pass `algorithm` to `myBlowfish`'s constructor directly: `Blowfish myBlowfish(algorithm);` or, when used in a header file: `public: Blowfish myBlowfish = Blowfish(algorithm);` or, using the owning class's constructor: `public: Blowfish myBlowfish; ... GameCryptography::GameCryptography(unsigned char key[]) : myBlowfish(algorithm) { }` – Remy Lebeau May 05 '23 at 20:52