I've been learning c++ for about 6 or 7 months now, and I've been messing around with a few systems that I'll hopefully use in a game I'll make one day. I don't know anything about graphics yet, so most of my experiments have been more about managing classes. For my latest experiment, I want to set up the system that delivers different types of effects to an enemy from a bullet fired by the player. For instance, it could have a freeze property that slows the enemy down, or a shock property that does added damage to shields and so on. My initial instinct is to make a projectile class contains has a vector of effect classes as a member. The player too, will have a vector of effects as a member. When the player fires a bullet, the player object's vector is copied onto the projectile. When the projectile connects with an enemy, it runs through the list of effects and applies each.

My concern/question is: is that too much information for each projectile to contain, or is this a somewhat typical setup? If I have dozens or maybe even hundreds of projectiles, each with that much information associated, could that become a dangerous amount of processing to run for every frame?

Like I said, I'm pretty new to programming, so if this is way off I'd appreciate a pointer or two. But if this will work for the small scale that I'm at now I'll continue building the system just for practice. Basically I just don't want any bad habits to develop this early in my education.

I think you've pretty much got the right idea. When you talk about vectors I assume you are talking about std::vector? One thing I'd suggest is to not copy vectors into the projectile class as this may start getting expensive depending on the size of the vector and how many times per frame you are doing it. Instead I would either have the projectile store a pointer back to the character that created it. This way you can access the effect vector you were talking about without any copying. Or use bit flags to hold a projectiles effects rather than a vector. This will reduce memory consumption and probably be faster to process. You can read a little about bit manipulation here

These options depend on what information you need to store and how it will be accessed.

Will every projectile be different? I do not think so, we can say that every projectile behaves according to its type. Make every projectile have some kind of reference to its type (enum, pointer, reference, ID...). That is 8 bytes overhead at most, which is perfectly okay. You then modify the enemy using the projectile type and are okay.

I want to set up the system that delivers different types of effects to an enemy from a bullet fired by the player. For instance, it could have a freeze property that slows the enemy down, or a shock property that does added damage to shields and so on.

...
My concern/question is: is that too much information for each projectile to contain, or is this a somewhat typical setup? If I have dozens or maybe even hundreds of projectiles, each with that much information associated, could that become a dangerous amount of processing to run for every frame?

Is it too much? I don't think so. Is it typical? Sort of, RPGs for example often have elemental damage properties. For your initial design, implement whatever gets you there. Iterate if necessary.

Keep in mind you'll need far more design than you probably expect. For example, how do you freeze a generic player-controlled entity? A generic enemy? A generic object in the world?

Stacking effects will be a problem. In certain games, ice cancels fire. On others (such as Torchlight) the various elemental damages are applied independently.

As said, those projectile types are going to be "static" in behaviour (albeit they might have random values on a per-instance basis). I strongly suggest the use of a reference type or a pointer. As for the values themselves, a preallocated std::vector will probably be fine (personally I think all bullets should be born equal).

I don't think the system "by itself" should care about who shoot the projectile. But sure it would be handy to have this property on another system to understand who-killed-who. As a side note, there's the need to generalize this in Damage entities if you care about environmental damage.

Bit fields at this stage are very early optimization, they don't look very appealing in a very hi-level system like this.