Well typically 2D RPG maps are built using layers. A layer may contain either tiles or objects (sprites). Typically you don't want to have something like a house be an object, because such a large, static structure is better constructed using tiles (since you can change up the size and display of the house more easily that way). I'll give you a simplified explanation of the class modeling in my own RPG.
We have a class called MapMode which is the highest level class and implements the main loading, update and draw code. This class got really big in the past because there's so many different things it needs to do, so we decided to create some helper classes to it that are responsible for handling specific operations on the map. Two of these classes are called TileSupervisor, which manages everything having to do with tiles and tile layers, and the ObjectSupervisor, which manages all of the sprites and the map's collision grid. Naturally, our tile layers are managed by TileSupervisor while the object layers are managed by ObjectSupervisor. We can have any number of tile/object layers and their draw order can be arranged and re-arranged in any way we like, but for simplicity let's assume we'll always have 3 tile layers and 1 object layer.
Our map is built using several layers of tiles, where each layer is like a 2D array. The same tile image may be drawn in more than one location, so it's inefficient to store several copies of the images. The TileSupervisor class maintains a vector of tile images, and our layers are nothing more than integers that index into that vector to extract the desired image to draw. Now we could either create a 2D array for every tile, or we could create a single 2D array and store the layer information for all tiles in there. We went with the latter approach. The MapTile class is a very simple wrapper around a 1D vector. This vector contains the indexes into the tile images container for each tile layer. So if we wanted to draw a tile that was located at the X, Y position on the map for a layer Z, we would access the 2D array of MapTile objects, index the X, Y element of this array, extract the Zth element from the MapTile object, and use this integer to index into the tile images container to extract the image to draw.
Now let's talk about objects. We define a MapObject as an entity with an x, y position on the map that has a height and length property, indicating how large the object is. We also have other properties we can set for objects such as whether or not to draw the object if it is on the screen (visibility toggle). We have a base class called MapObject which is abstract and contains these common properties, as well as pure virtual functions for drawing and updating the object. We have a number of classes derive from MapObject to support different types of objects on a map.
- PhysicalObject is a static object that does not move. A tree could be a physical object, for instance.
- TreasureObject is derived from PhysicalObject and can be interacted with by the player to extract treasure contents.
- VirtualSprite is a sprite (moving object) with no image. This serves both as a base class for other sprites, and can also be used as a map camera (our camera is always focused on a map object).
- MapSprite implements NPCs and player-controlled sprites. They can have dialogs, be given movement commands, etc.
- EnemySprite is derived from MapSprite and causes a battle to occur when it collides with the player controlled sprite.
The ObjectSupervisor maintains a vector of MapObjects for each object layer. When it's time to update the map, the code will go through and call the update function on every object to update their animations, change their position, perform collision detection, etc. To improve performance, we keep the objects in this container sorted based on their draw order (you want to draw objects on the screen from top to bottom). So when we call the draw function, we already have a draw-order sorted container of objects and can simply iterate through the container and draw each object that should be visible on the screen.
------------------------
Hope that starts to get the gears moving in your head about how you can go about implementing tiles and objects and layers on a map. The map code for an RPG is probably the most complex piece of the game and it will take time and practice before things start to make sense. I didn't even get into other map aspects like dialogues, events, pathfinding, and so on. My project is reasonably well documented (certainly more so than most) and the code is open source, so you are welcome to study it and learn if you like.
http://www.allacrost.org/wiki/index.php/Map_Mode
Documents the design and structure of our map code. Somewhat incomplete, but covers the most important aspects.
https://sourceforge.net/p/allacrost/code/HEAD/tree/trunk/game/
Source code - main directory
https://sourceforge.net/p/allacrost/code/HEAD/tree/trunk/game/src/modes/map/
Source code - map directory
You can also download it and run Doxygen on the source tree. This tool will build the API documentation and can also do things like construct class hierarchy diagrams to give you a better understanding of each piece of the code and how they all tie together. Again though, this is pretty complex and is definitely above the scope of what you're aiming to do with your project. Hope you find this information helpful.